https://www.jianshu.com/p/c98eb98bd00cjavascript
相信凡是写过javascript的童鞋也必定都写过回调方法(callback),简单说回调方法就是将一个方法func2做为参数传入另外一个方法func1中,当func1执行到某一步或者知足某种条件的时候才执行传入的参数func2,例以下面的代码段html
// 当参数a大于10且参数func2是一个方法时 执行func2 function func1(a, func2) { if (a > 10 && typeof func2 == 'function') { func2() } } func1(11, function() { console.log('this is a callback') })
通常来讲咱们会碰到的回调嵌套都不会不少,通常就一到两级,可是某些状况下,回调嵌套不少时,代码就会很是繁琐,会给咱们的编程带来不少的麻烦,这种状况俗称——回调地狱。极端状况以下图:java
由此,Promise的概念就由社区提出并实现,做用与回调方法几乎一致,都是在某种状况下执行预先设定好的方法,可是使用它却可以让代码变得更简洁清晰编程
Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败api
当Promise的状态又pending转变为resolved或rejected时,会执行相应的方法,而且状态一旦改变,就没法再次改变状态,这也是它名字promise-承诺的由来数组
在ES6中,Promise终于成为了原生对象,能够直接使用。可是在这以前,小伙伴们想要使用Promise,通常会借助于第三方库,或者当你知道其中的原理之后,也能够手动实现一个简易的Promisepromise
固然,为了防止不可预知的bug,在生产项目中最好仍是不要使用原生的或者本身编写的Promise(目前为止并非全部浏览器都能很好的兼容ES6),而是使用已经较为成熟的有大量小伙伴使用的第三方Promise库,下面就为小伙伴推荐一个—— Bluebird浏览器
// 方法1 let promise = new Promise ( (resolve, reject) => { if ( success ) { resolve(a) // pending ——> resolved 参数将传递给对应的回调方法 } else { reject(err) // pending ——> rejectd } } ) // 方法2 function promise () { return new Promise ( function (resolve, reject) { if ( success ) { resolve(a) } else { reject(err) } } ) }
注意:实例化的Promise对象会当即执行异步
.then()方法使Promise原型链上的方法,它包含两个参数方法,分别是已成功resolved的回调和已失败rejected的回调异步编程
promise.then(
() => { console.log('this is success callback') }, () => { console.log('this is fail callback') } )
.catch()的做用是捕获Promise的错误,与then()的rejected回调做用几乎一致。可是因为Promise的抛错具备冒泡性质,可以不断传递,这样就可以在下一个catch()中统一处理这些错误。同时catch()也可以捕获then()中抛出的错误,因此建议不要使用then()的rejected回调,而是统一使用catch()来处理错误
promise.then(
() => { console.log('this is success callback') } ).catch( (err) => { console.log(err) } )
一样,catch()中也能够抛出错误,因为抛出的错误会在下一个catch中被捕获处理,所以能够再添加catch()
使用rejects()方法改变状态和抛出错误 throw new Error() 的做用是相同的
当状态已经改变为resolved后,即便抛出错误,也不会触发then()的错误回调或者catch()方法
then() 和 catch() 都会返回一个新的Promise对象,能够链式调用
promise.then(
() => { console.log('this is success callback') } ).catch( (err) => { console.log(err) } ).then( ... ).catch( ... )
// p1异步方法中返回p2 let p1 = new Promise ( (resolve, reject) => { resolve(p2) } ) let p2 = new Promise ( ... ) // then()中返回promise let p3 = new Promise ( (resolve, reject) => { resolve() } ) let p4 = new Promise ( ... ) p3.then( () => return p4 )
p1异步方法中返回p2
p1的状态取决于p2,若是p2为pending,p1将等待p2状态的改变,p2的状态一旦改变,p1将会当即执行本身对应的回调,即then()中的方法针对的依然是p1
then()中返回promise
因为then()自己就会返回一个新的promise,因此后一个then()针对的永远是一个新的promise,可是像上面代码中咱们本身手动返回p4,那么咱们就能够在返回的promise中再次经过 resolve() 和 reject() 来改变状态
用来包装一个现有对象,将其转变为Promise对象,但Promise.resolve()会根据参数状况返回不一样的Promise:
参数是Promise:原样返回
参数带有then方法:转换为Promise后当即执行then方法
参数不带then方法、不是对象或没有参数:返回resolved状态的Promise
Promise.reject()会直接返回rejected状态的Promise
参数为Promise对象数组,若是有不是Promise的对象,将会先经过上面的Promise.resolve()方法转换
var promise = Promise.all( [p1, p2, p3] ) promise.then( ... ).catch( ... )
当p一、p二、p3的状态都变成resolved时,promise才会变成resolved,并调用then()的已完成回调,但只要有一个变成rejected状态,promise就会马上变成rejected状态
var promise = Promise.race( [p1, p2, p3] ) promise.then( ... ).catch( ... )
“竞速”方法,参数与Promise.all()相同,不一样的是,参数中的p一、p二、p3只要有一个改变状态,promise就会马上变成相同的状态并执行对于的回调
Promise.done() 的用法相似 .then() ,能够提供resolved和rejected方法,也能够不提供任何参数,它的主要做用是在回调链的尾端捕捉前面没有被 .catch() 捕捉到的错误
Promise. finally() 接受一个方法做为参数,这个方法无论promise最终的状态是怎样,都必定会被执行