一篇看懂Promise什么是Promise$.ajax({success:(res)=>{$.ajax({success:(res)=>{$.ajax({success:(res)=>{//...}})}})}})这是一个典型的回调地狱,不仅代码臃肿,可读性差,而且耦合度太高,不好理解维护。代码无法复用,容易隐藏bug。Promise规范的出现就是为了解决这个问题。这里强调一下,Promise是一个解决方案,是一个规范。ES6原生提供了Promise对象,在日常开发中经常会遇到与Promise相关的操作。本文将介绍Promise的使用方法及相关原理,希望能有所帮助。Promise有三种状态:Pending(等待状态)Fulfilled(成功状态)Rejected(失败状态)Promise的特点是状态只能从Pending转换为Fulfilled或Rejected,一旦改变就不会改变。newPromise((resolve,reject)=>{/*executor*/})Promise是一个带有resolve和reject参数的构造函数(执行器)。创建Promise时会立即执行此构造函数。resolve和reject函数被调用时,分别将Promise的状态改变为fulfilled(成功状态)和rejected(失败状态),并传递成功值或失败原因。.执行器通常在内部执行一些异步操作。当异步操作完成后,可以根据执行结果(可能成功也可能失败)相应地调用resolve或reject。如果执行者抛出错误,Promise也会失败。Promise原型还有then和catch方法,调用后返回一个Promise实例,所以可以链式调用。每个Promise实例都有一个then方法,该方法有两个参数(onFulfilled,onRejected),分别是Promise成功和失败时的回调。letp=newPromise((resolve,reject)=>{resolve('success');})p.then(value=>{console.log(value);//success}).then(value=>{console.log(value);//没有返回值时,undefined})当返回一个值或者成功的Promise时,则此时返回的Promise是成功的,如果没有返回值,也是成功的,而回调函数的参数值是undefind。当抛出错误或返回失败的Promise时,此时返回的Promise全部失败。letp=newPromise((resolve,reject)=>{reject('fail');})p.then(()=>{},err=>{console.log(err);//fail});then方法传递的成功/失败函数,这两个函数可以返回一个promise;如果返回一个promise,promise的状态将被用作下一个then的结果。让p=newPromise((resolve,reject)=>{resolve('success')});让p2=newPromise((resolve,reject)=>{resolve('success2')})p.then(value=>{returnp2;//p2的成功状态会作为下一个then的状态}).then(value=>{console.log(value)})Promise.prototype.catch方法return也是一个Promise,用法同then方法,用于处理异常捕获的情况。该方法的捕获属于就近捕获原则。离错误最近的catch会捕获错误并处理,后面就不会再捕获了。如果失败状态是由then方法中的失败函数回调触发的,catch方法不会捕捉到。letp1=newPromise((resolve,reject)=>{resolve('success');});p1.then(value=>{throw'anewerror';}).catch(e=>{console.log(e);//一个新的错误}).then(()=>{console.log('afteracatchthechainisrestored');})Promise.all方法返回一个新的Promise对象,在参数只有当对象中的所有promise对象都成功时才会触发成功状态,一旦任何一个对象失败,就会立即触发promise对象的失败状态。当触发成功状态时,会依次返回一个包含所有Promise返回值的数组。如果违反失败状态,将返回第一个失败的Promise对象的错误消息。letp1=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('p1')},0)});letp2=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('p2')},0)});letpromise=Promise.all([p1,p2]).then(value=>{console.log(value);//['p1','p2']})Promise.race方法将参数中任何一个完成状态转换的第一个Promise作为成功或失败状态,返回Promise对象。letp1=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('p1')},1000)});letp2=newPromise((resolve,reject)=>{setTimeout(()=>{reject('p2')},0)});Promise.race([p1,p2]).then((value)=>{console.log(value)},(err)=>{console.log(err);//p2})Promise.resolve(value)返回成功状态,并将该值传递给相应的then方法;Promise.reject(reason)返回失败状态,并通过reason对应的then方法。Promise的优缺点优缺点解决回调不能监听状态链式调用新立即执行,不能取消减少嵌套内部错误不能抛出Promise实践(Node环境)1.等待状态constpromise1=newPromise((resolve,reject)=>{setTimeout(()=>{resolve('success')},1000)})constpromise2=promise1.然后(()=>{返回'一个错误'})控制台。日志('promise1',promise1)console.log('promise2',promise2)setTimeout(()=>{console.log('promise1',promise1)console.log('promise2',promise2)},2000)2.状态改变constpromise=newPromise((resolve,reject)=>{resolve('success1')reject('error')resolve('success2')})promise.then((res)=>{console.log('then:',res)}).catch((err)=>{console.log('catch:',err)})3.对Promise.resolve(1).then((res)=>{console.log(res)return2}).catch((err)=>{return3}).then((res)=>{console.log(res)})4.链式调用constpromise=newPromise((resolve,reject)=>{setTimeout(()=>{console.log('executor')resolve('success')},1000)})conststart=Date.now()promise.then((res)=>{console.log(res,Date.now()-开始)})promise.then((res)=>{console.log(res,Date.now()-start)})//Promise的构造函数只执行一次,立即执行;promise的then方法可以执行多次调用,每次都返回一个新的promise实例constpromise=newPromise((resolve,reject)=>{setTimeout(()=>{console.log('executor')resolve('success')},1000)})constpromise2=promise.then(res=>{console.log(res);})promise2.then(res=>{console.log(res)})5.错误捕获Promise.resolve().then(()=>{returnnewError('error!!!')}).then((res)=>{console.log('then:',res)}).catch((err)=>{console.log('catch:',err)})Promise.resolve().then(()=>{thrownewError('error');//returnPromise.reject('error')}).then((res)=>{console.log('then:',res)}).catch((err)=>{console.log('catch:',err)})then或者catch方法返回一个错误对象,不会被捕获,只有当抛出错误或捕获仅在返回失败状态时引起。6.引用错误constpromise=Promise.resolve().then(()=>{returnpromise})promise.catch(e=>{console.log(e)})//[TypeError:Chainingcycledetectedforpromise#
