zoukankan      html  css  js  c++  java
  • Promise 详解

      在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。原来异步执行都用回调函数实现,现在可以使用Promise来实现异步。

      有时在业务中需要执行一层套一层套一层...的异步回调来获取数据,也就是地狱回调,

    $.ajax({
        url:"",
        success: function(res1){
            $.ajax({
                url:"",
                data: {key:res1},
                success: function(res2){
                    $.ajax({
                        url:"",
                        data: {key:res2},
                        success:function(res3){
                            
                        }
                    })
                }
            })
        }
    })

      现在可以使用Promise来解决地狱回调的复杂嵌套问题。

    var p = new Promise((res,rej)=>{
        let data = 10;
       // 使用setTimeout模拟异步,data是异步请求回的数据,setTimeout其实有三个值,第三个值是第一个值函数的参数
       setTimeout(res,1000,data+data)
    });
    function a(data){
        return new Promise((res,rej)=>{
            setTimeout(res,1000,data+data)
        })
    };
    function b(data){
        return new Promise((res,rej)=>{
            setTimeout(res,1000,data+data)
        })
    };
    p.then(function(res){
        console.log(res); // 20
        return a(res)
    }).then(function(res){
        console.log(res); //40
        return b(res)
    }).then(function(res){
        console.log(res); //80
    });        

    描述

      Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。

    一个 Promise有以下几种状态:
    
    pending: 初始状态,既不是成功,也不是失败状态。
    fulfilled: 意味着操作成功完成。
    rejected: 意味着操作失败

      pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。

    因为 Promise.prototype.then 和  Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。

      

    语法

    new Promise( function(resolve, reject) {...}
    

    方法 

      1、Promise.prototype.catch(onRejected)添加一个拒绝(rejection) 回调到当前 promise, 返回一个新的promise。当这个回调函数被调用,新 promise 将以它的返回值来resolve,否则如果当前promise 进入fulfilled状态,则以当前promise的完成结果作为新promise的完成结果

      2、.Promise.prototype.then(onFulfilled, onRejected)添加解决(fulfillment)和拒绝(rejection)回调到当前 promise, 返回一个新的 promise, 将以回调的返回值来resolve.

      3、Promise.prototype.finally(onFinally)添加一个事件处理回调于当前promise对象,并且在原promise对象解析完毕后,返回一个新的promise对象。回调会在当前promise运行完毕后被调用,无论当前promise的状态是完成(fulfilled)还是失败(rejected)

      备注:由于 then() 和 catch()方法都会返回 promise,它们可以被链式调用,由此才可以实现then的链式调用来实现多重回调 

    实例

      1、一般promise

    var p = new Promise(function(resolve,reject){
      // 当异步代码执行成功时,我们才会调用resolve(...),当异步代码失败时调用reject(...);
      // 使用setTimeout(...)来模拟异步代码
    if(Math.random()>0.5){ setTimeout(resolve,1000,res) }else{ setTimeout(reject,1000,rej) } }); p.then(function(res){ console.log(res); }).catch(function(rej){ console.log(rej); });

      2、当promise的then中存在两个函数,且走reject回调失败时,catch中的错误回调无效

    var a = new Promise((resolve,reject)=>{
        if(false){
            resolve('这是大于0.5')
        } else {
            reject("这是小于等于0.5");
        }
    });
    a.then(
        function(res){console.log("then");console.log(res)}
    ).catch(
        function(res){console.log("catch");console.log(res)} // catch 这是小于等于0.5
    );
    a.then(
        function(res){console.log("then");console.log(res)},
        function(rej){console.log("then");console.log(rej)} // then 这是小于等于0.5
    ).catch(
        function(rej){console.log("catch");console.log(rej)}
    );

      3、地狱回调:不同人写的处理地狱回调方式中return的数量不一样,造成困惑,仔细观察还是有不同

    function multiply(input) {
        return new Promise(function (resolve, reject) {
            console.log('calculating ' + input + ' x ' + input + '...');
            setTimeout(resolve, 500, input * input);
        });
    };
    function add(input) {
        return new Promise(function (resolve, reject) {
            console.log('calculating ' + input + ' + ' + input + '...');
            setTimeout(resolve, 500, input + input);
        });
    };
    var p = new Promise(function (resolve, reject) {
        console.log('start new Promise...');
        resolve(123);
    });
    // 这是把自定义函数直接当做then中的匿名函数,所有只需要在自定义的函数中返回promise就可以实现then的链式调用 p.then(multiply) .then(add) .then(multiply) .then(add) .then(function (result) { console.log(
    'Got value: ' + result); });
    // 严格按照then中的匿名函数写法,先是自定义函数内部return出promise实例,再在匿名函数中return出promise实例,这样就可以实现then的链式调用
    p.then(
      function(res){
        return multiply(res)
      }
    ).then(
      function(res){
        return add(res)
      }
    )
    .then(
      function(res){
        return multiply(res)
      }
    ).then(
      function(res){
        return add(res)
      }
    ).then(
      function(res){
        console.log('Got value'+res)
      }
    )
    
    

    Promise.all(iterable) :iterable是一个可迭代对象,如 Array 或 String

      Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中  promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

    const p1 = Promise.resolve(3);
    const p2 = 42;
    const p3 = new Promise(function(resolve, reject) {
      setTimeout(resolve, 100, 'foo');
    });
    const p4 = new Promise(function(resolve,reject){
      setTimeout(reject,1000,'fail')
    }) Promise.all([p1, p2, p3]).then(function(values) { console.log(values); });
    // expected output: Array [3, 42, "foo"]

    Promise.all([p1,p2,p3,p4]).then(function(res){
      console.log(res)
    }).catch(function(rej){
      console.log("rej:"+rej)
    })
    //
    expected output: String rej:fail

    Promise.race(iterable) :iterable是一个可迭代对象,如 Array 或 String

      顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态,如果出现同时,那么久看Promise的哪个实例的位置,实例最早,就返回那个结果,无论成功状态还是失败状态。不是race中数组的位置,是在js中promise实例位置。

      

    let p1 = new Promise(function(resolve,reject){
    		setTimeout(resolve,1000,"时间1000,p1的resolve成功")
    	});
    	let p2 = new Promise(function(resolve,reject){
    		setTimeout(resolve,500,'时间:500,p2的resolve成功')
    	})
    	let p3 = new Promise(function(resolve,reject){
    		setTimeout(reject,1000,"时间1000,p3的reject失败")
    	});
    	let p4 = new Promise(function(resolve,reject){
    		setTimeout(reject,500,'时间:500,p4的reject失败')
    	});
    	let p5 = new Promise(function(resolve,reject){
    		setTimeout(resolve,1000,'时间:1100,p5的resolve成功')
    	});
    	Promise.race([p1,p2]).then(function(res){
    		console.log(res);  // 时间500,p2的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p1,p3]).then(function(res){
    		console.log(res); // 时间1000,p1的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p3,p1]).then(function(res){
    		console.log(res); // 时间1000,p1的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p1,p5]).then(function(res){
    		console.log(res); // 时间1000,p1的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p5,p1]).then(function(res){
    		console.log(res); // 时间1000,p1的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p1,p4]).then(function(res){
    		console.log(res);
    	}).catch(function(rej){
    		console.log(rej); // 时间:500,p4的reject成功
    	});
    	Promise.race([p2,p3]).then(function(res){
    		console.log(res); // 时间:500,p2的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p2,p4]).then(function(res){
    		console.log(res); // 时间:500,p2的resolve成功
    	}).catch(function(rej){
    		console.log(rej);
    	});
    	Promise.race([p3,p4]).then(function(res){
    		console.log(res);
    	}).catch(function(rej){
    		console.log(rej); // 时间:500,p4的reject失败
    	});
    

    Promise.reject()方法返回一个带有拒绝原因的Promise对象

      静态函数Promise.reject返回一个被拒绝的Promise对象。通过使用Error的实例获取错误原因reason对调试和选择性错误捕捉很有帮助。

    function resolved(result) {
      console.log('Resolved');
    }
    
    function rejected(result) {
      console.error(result);
    }
    
    Promise.reject(new Error('fail')).then(resolved, rejected);
    // expected output: Error: fail
    

    Promise.resolve(value)

      返回一个以给定值解析后的Promise 对象。如果这个值是一个 promise ,那么将返回这个 promise ;如果这个值是thenable(即带有"then" 方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。

    // Resolve一个thenable对象
    var p1 = Promise.resolve({ 
      then: function(onFulfill, onReject) { onFulfill("fulfilled!"); }
    });
    console.log(p1 instanceof Promise) // true, 这是一个Promise对象
    
    p1.then(function(v) {
        console.log(v); // 输出"fulfilled!"
      }, function(e) {
        // 不会被调用
    });
    
    // Thenable在callback之前抛出异常
    // Promise rejects
    var thenable = { then: function(resolve) {
      throw new TypeError("Throwing");
      resolve("Resolving");
    }};
    
    var p2 = Promise.resolve(thenable);
    p2.then(function(v) {
      // 不会被调用
    }, function(e) {
      console.log(e); // TypeError: Throwing
    });
    
    // Thenable在callback之后抛出异常
    // Promise resolves
    var thenable = { then: function(resolve) {
      resolve("Resolving");
      throw new TypeError("Throwing");
    }};
    
    var p3 = Promise.resolve(thenable);
    p3.then(function(v) {
      console.log(v); // 输出"Resolving"
    }, function(e) {
      // 不会被调用
    });
    

      

  • 相关阅读:
    web安全之sql注入实例(5.0之前的)
    http和htpps
    web安全之sql注入原理
    web安全之http协议
    题解洛谷P1538【迎春舞会之数字舞蹈】
    [模板]洛谷T3375 KMP字符串匹配
    [模板]洛谷T2158 仪仗队 欧拉函数
    洛谷T1967 货车运输 Kruskal最大生成树&&倍增LCA
    [模板]洛谷T3380 二逼平衡树 线段树套BST
    [模板]洛谷T3384 树链剖分
  • 原文地址:https://www.cnblogs.com/aidixie/p/12790297.html
Copyright © 2011-2022 走看看