说明
Promise是一个构造函数,自己身上有call、resolve、reject,原型上有then、catch等方法。
Promise 对象有以下两个特点。
- 对象的状态不受外界影响。有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。
这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
开始
初步理解
var promise = new Promise(function(resolve, reject) {setTimeout(function(){console.log('完成')resolve('随便什么东西')}, 2000)})
类似这样,Promise的构造函数接受一个参数:函数。并且会传入两个参数resolve、reject,用来表示成功或者失败。
一般情况会把promise放在一个函数中,当函数调用时候才会执行promise的操作。
function runAsync(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){console.log('执行完成');resolve('随便什么数据');}, 2000);});return p;}runAsync().then(function(data){console.log(data);//后面可以用传过来的数据做些其他操作//......});
表面上看Promise只是简化层层的回调写法,实质上,Promise的精髓是状态
链式操作的用法
function runAsync1(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){console.log('异步任务1执行完成');resolve('随便什么数据1');}, 1000);});return p;}function runAsync2(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){console.log('异步任务2执行完成');resolve('随便什么数据2');}, 2000);});return p;}function runAsync3(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){console.log('异步任务3执行完成');resolve('随便什么数据3');}, 2000);});return p;}
runAsync1().then(function(data){console.log(data);return runAsync2();}).then(function(data){console.log(data);return runAsync3();}).then(function(data){console.log(data);});

runAsync1().then(function(data){console.log(data);return runAsync2();}).then(function(data){console.log(data);return '直接返回数据'; //这里直接返回数据}).then(function(data){console.log(data);});

reject的用法
reject的作用就是把Promise的状态置为rejected,这样我们在then中就能捕捉到,然后执行“失败”情况的回调。
then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。
var promise = new Promise((resolve, reject) => {reject('失败')})promise.then((data) =>{console.log('success:' + data)},(reason) => {console.log('error:' + reason);})
catch的用法
Promise除了then还有catch方法,他和then的第二个参数一样,用来指定reject的回调。但是他还有一个作用:当在执行resolve的回调时候,如果出现异常那么js不会卡死,而是会进入到catch方法中。
当catch上面有处理reject的函数时候,会一级一级的处理,而不是直接跳到catch中。
function getNumber(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){var num = Math.ceil(Math.random()*10); //生成1-10的随机数if(num<=5){resolve(num);}else{reject('数字太大了');}}, 2000);});return p;}getNumber().then(function(data){console.log(data);console.log(somedata); //此处的somedata未定义}).then((data) =>{console.log('success:' + data)},(reason) => {console.log('error:' + reason);}).catch(function(reason){console.error(reason);});
all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
Promise.all([runAsync1(), runAsync2(), runAsync3()]).then(function(results){console.log(results);});

race的用法
all => 谁跑的慢,以谁为准执行回调
race => 谁跑的快,以谁为准执行回调
Promise.race([runAsync1(), runAsync2(), runAsync3()]).then(function(results){console.log(results);});

在then里面的回调开始执行时,runAsync2()和runAsync3()并没有停止,仍旧再执行。于是再过1秒后,输出了他们结束的标志。
race的应用场景
function requestImg(){var p = new Promise(function(resolve, reject){var img = new Image();img.onload = function(){resolve(img);}img.src = 'xxxxxx';});return p;}//延时函数,用于给请求计时function timeout(){var p = new Promise(function(resolve, reject){setTimeout(function(){reject('图片请求超时');}, 5000);});return p;}Promise.race([requestImg(), timeout()]).then(function(results){console.log(results);}).catch(function(reason){console.log(reason);});

finally
finally方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
promise.then(result => {···}).catch(error => {···}).finally(() => {···});
finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
finally本质上是then方法的特例。
Promise的异常捕获方式
在Promise的构造体内进行错误处理
var promise=new Promise(function(resolve,reject){try {throw new Error('test');}catch(e){reject(e)}})
通过Promise.prototype.catch来进行错误处理
var promise=new Promise(function(resolve,reject){reject(new Error('test'));})promise.catch(function(e){//something to deal with the errorconsole.log(e)})
catch方面里面还可以再抛错误,这个错误会被后面的catch捕获
var promise=new Promise(function(resolve,reject){reject(new Error('test1'))})promise.catch(function(e){console.log(e);throw new Error('test2')}).catch(function(e){console.log(e)})// Error : test1// Error : test2
Promise.all中的异常捕获
如果组成Promise.all的promise有自己的错误捕获方法,那么Promise.all中的catch就不能捕获该错误。
var p1=new Promise(function(resolve,reject){reject(new Error('test1'))}).catch(function(e){console.log("由p1自身捕获",e);})var p2=new Promise(function(resolve,reject){resolve();})var p=Promise.all([p1,p2]);p.then(function(){}).catch(function(e){//在此处捕获不到p1中的errorconsole.log(e)})//由p1自身捕获 Error: test1
在promise中无法被捕获的错误
在promise实例resolve之后,错误无法被捕获。
var promise=new Promise(function(resolve,reject){resolve();throw new Error('test');//该错误无法被捕获})promise.then(function(){//}).then(function(e){console.log(e)})
支持


常见问题
参考
总结
无
