目录
异步和同步
异步的问题
new Promise语法
promise的状态
promise.then()
Promise.resolve()
Promise.reject()
Promise.all()
Promise.race()
Promise.catch()
Promise.finally()
异步和同步
同步模式下,代码按顺序执行,前一条执行完毕后,进行后一条的执行。
异步模式下,代码可以不按顺序执行,不同行的代码可以同时执行。
异步的问题
有时,一条代码需要一个异步操作的返回值才能进行计算,这就会导致回调问题,promise语法可以优雅地解决回调。
new Promise语法
new Promise用于创建Promise实例,其参数是一个函数。
const demo = new Promise( ( resolve, reject )=>{if(){...resolve(); }if(){...reject();}}
)
作为参数的函数接收两个参数。为resolve和reject(参数名可以修改,但一般都用resolve和reject),resolve和reject也为函数。
promise的状态
promise实例具有三个状态:成功(fulfilled,但有时也叫resolved)、失败、待定。
当调用resolve()函数时,promise的状态会变成成功。
当调用reject()函数时,promise的状态会变为失败。
当promise的状态为成功或失败时,会进入Promise.then()。
在new Promise中,若调用throw,会触发reject状态。
let a = new Promise((resolve,reject)=>{throw Error('error!');});console.log(a);
promise.then()
接收两个参数,第一个参数是promise状态变为成功时,执行的函数,第二个参数是promise状态为失败时调用的函数。
demo.then(()=>{//如果resolve被触发,执行的函数},()=>{//如果reject被触发,执行的函数}
)
传参
在new Promise参数函数中,reject和resolve可以传递参数,在.then对应的处理函数中,可以获得这个参数,且两个参数的名称不需要对应。
const demo = new Promise( ( resolve, reject )=>{if(){...resolve(num1); }if(){...reject(num2);}}).then((resolveData)=>{...},(rejectData)=>{})
.then中的参数名resolveData和rejectData是可以修改的,这里只是随便起的名字,不是一定要叫这个。
Promise.resolve()
Promise.resolve()方法返回一个Promise对象。
Promise.resolve的参数为非Promise参数时,其返回的Promise对象状态为成功,值为传入的参数。
若Promise.resolve的参数为Promise参数,其返回的Promise对象的状态与值,取决于参数Promise。
let a = Promise.resolve(1);let b = Promise.resolve(function(){return 1+1;});let c = Promise.resolve(new Promise((resolve,reject)=>{reject();}));console.log(a);console.log(b);console.log(c);
Promise.reject()
与Promise.resolve()类似。
但与resolve不同的是,不管传入的参数如何,返回的Promise状态都是失败。
传入的参数是什么,该参数的返回值会成为返回的Promise的值。
即使传入的参数是成功的Promise对象,返回值也是失败的Promise。
let a = Promise.reject(new Promise((resolve,reject)=>{resolve("resolve!!!");}));console.log(a);
当传入的参数是成功的Promise,这个Promise会作为失败Promise的值。但返回的Promise状态仍然是失败。
当传入的参数是失败的Promise,整个失败的Promise会作为返回的Promise的值。
let a = Promise.reject(new Promise((resolve,reject)=>{reject("reject!!!");}));console.log(a);
Promise.all()
Promise.all()方法接收一个数组。
该数组一般情况下,其中每一个元素都是Promise。
其返回的结果也是Promise,只有当数组中所有的Promise都成功时,才返回成功,成功的结果是每个Promise对象成功结果组成的一个数组,否则返回失败,失败的结果是第一个失败的Promise的结果。
Promise全成功的情况下:
若传入的参数不是Promise,则该参数会被视为成功值。
let p1 = Promise.resolve(1);let p2 = 2;let p3 = Promise.resolve(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let a = Promise.all([p1,p2,p3,p4]);console.log(a);
有失败Promise的情况下:
let p1 = Promise.resolve(1);let p2 = 2;let p3 = Promise.reject(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let p5 = new Promise((resolve,reject)=>{reject('reject');})let a = Promise.all([p1,p2,p3,p4,p5]);console.log(a);
Promise.race()
Promise.race()方法接收一个数组。
该数组一般也都由Promise组成。返回值为第一个改变状态的Promise。
当数组元素为非Promise结构时,该非Promise结构会被视为成功的Promise并返回。
let p1 = Promise.resolve(1);let p2 = null;let p3 = Promise.reject(3);let p4 = new Promise((resolve,reject)=>{resolve('ok');});let p5 = new Promise((resolve,reject)=>{reject('reject');})let a = Promise.race([p2,p1]);
Promise.catch()
Promise.catch()的语法有点像语法糖。
Promise.catch(reject)从语法上讲,相当于promise.then(null, reject),这里的reject都是指处理reject状态的回调函数。
.catch返回值也是一个Promise。
Promise.finally()
Promise.finally()方法,不论Promise的状态是成功还是失败,在最后都会调用finally中的方法。
finally可以用于处理不论返回结果如何,都需要执行的逻辑,可以避免代码冗余。
finally接收的是一个函数。
finally的返回值是一个新的Promise实例对象。
该对象的状态一般是父Promise状态的传递。父Promise是指promise.finally中,promise对应的实例。但当finally的返回值是显式reject或pending Promise时,返回值是reject或pending。
下例中,pTest的返回值是一个状态为失败的Promise,调用pTest时,虽然finally参数的返回值是成功的promise,但是由于该promise的状态不是失败或待定,所以finally的返回值取决于父Promise,即pTest。
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{resolve('ok');})}));
但若finally参数返回的是reject或者pending,则返回值取决于参数。
参数返回reject的情况下:
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{reject('reject');})}));
参数返回panding的情况下:
let pTest = new Promise((resolve,reject)=>{reject('error');});console.log(pTest.finally( ()=>{return new Promise((resolve,reject)=>{})}));