乐趣区

Promise入门之基本用法

Promise 入门之基本用法
背景
在我们使用异步函数比如 ajax 进行编写代码,如果我们需要很多个 ajax 请求不同的接口,而下一个接口需要依赖上一个接口的返回值,这样,我们的代码则需要在各种回调函数中嵌套,这样一层一层地下去,就形成了回调地狱。但是 promise 的出现则不需要嵌套就能解决这个问题。什么是 promise?promise 本质其实是一个对象,用于传递异步操作的信息。并且 promise 这个对象提供了相对应的 API,满足我们的需求开发。
创建 promise 对象
let pro = new Promise(function(resolve, reject){
// 异步处理逻辑
// 处理完毕之后调用 resolve 或者 reject
})
promise 对象跟其他普通对象的创建方法一样,只需要 new 一个新的对象即可,接受一个函数作为参数,并且该函数中的参数分别为两个回调函数,用于进行不同的逻辑处理。在定完一个 promise 对象之后,我们可以通过调用 then 方法来执行其对应的逻辑
pro.then(function(res){
// 如果 promise 对象调用了 resolve 方法,则进入该函数逻辑
}, function(err){
// 如果 promise 对象调用了 reject 方法,则进入该函数逻辑
})
promise 的状态
promise 的实例主要有以下三种状态:①pending:处理中②fulfilled:成功③rejected:失败
pending 状态的 promise 可以转化为 fulfilled 状态或者 rejected 状态,该转化不可逆且只能转化一次。同时,fulfilled 状态和 rejected 状态只能由 pending 状态转化,相互不能转化。如图

pending 状态下的 promise 在处理完业务逻辑,且能正常退出时便可以执行 resolve 方法,从而进入 fulfilled 状态;若 pending 状态下的 promise 在处理业务逻辑的过程中出现异常错误,或者主动调用 reject 方法,则进入 rejected 状态。
let pro = new Promise(function(resolve, reject){
if(// 逻辑处理完毕且能正常退出){
resolve()
}
else{
// 异常错误抛出
reject()
}
})

pro.then(function(res){
// 如果 promise 对象调用了 resolve 方法,则进入该函数逻辑
}, function(err){
// 如果 promise 对象调用了 reject 方法,则进入该函数逻辑
})
链式调用
因为 promise 对象中的 then 方法的返回值是一个新的 promise 对象,因此可以实现链式调用。但后一个 then 方法的执行必须等待前一个 then 方法返回的 promise 对象状态转为 fulfilled 或者 rejected,若 promise 对象处于 pending 状态下,则后一个 then 方法只能等待。
pro.then(function(res){
// 第一个 promise 对象逻辑执行
return newPro;// 返回一个新 promise
}).then(function(res){
// 对 newPro 这个对象进行处理
})
// … 可以一直链式调用下去
异常捕捉
promise 中的 catch 方法其实就是 pro.then(null, rejection),用户捕捉代码运行中的错误异常。
pro.then(function(res){
// 逻辑处理,但存在异常
}).catch(function(err){
// 捕捉上一个 then 函数中所出现的异常错误
})
此外,catch 方法的所捕捉的异常不仅仅局限于上一个 then 方法内,而是可以把错误一直传递下来,直至遇到的第一个 catch,然后被捕捉。如链式调用中:
pro.then(function(res){
// 逻辑处理,但存在异常
}).then({
// 逻辑处理
}).catch(function(err){
// 捕捉上面第一个出现异常的 then 函数中所出现的错误
})
promise.all
promise.all 方法可以接受一个由 promise 组成的数组作为参数,包装成一个新的 promise 对象,并且按照数组中 promise 的顺序进行异步执行。如:
let pro1 = new Promise(function(resolve, reject){});
let pro2 = new Promise(function(resolve, reject){});
let pro3 = new Promise(function(resolve, reject){});

let proAll = promise.all([pro1, pro2, pro3]);
proAll 的状态由 pro1,pro2,pro3 三者共同决定:①pending: 处理中,pro1,pro2,pro3 中无 rejected 且存在 pending 状态。②rejected: pro1,pro2,pro3 中存在一个 rejected。③fulfilled:pro1,pro2,pro3 三者均为 fulfilled。
当 proAll 的状态为 fulfilled 时,会返回一个数组,该数组中的元素则是上面由 promise 组成的数组相对应执行后的结果。
promise.race
promise.race 所接受的参数与 promise.all 一致,但 promise.race 的返回值则是由 pro1,pro2,pro3 三者中最先完成的 promise 对象决定,并且返回值为该最早完成的 promise 对象的返回值。
let proAll = promise.race([pro1, pro2, pro3]);
promise.resolve
promise.resolve 方法能将一个对象转换成 promise 对象
let newPro = promise.resolve(obj);
①若 obj 不具有 then 方法,则 newPro 直接变为 fulfilled 状态
let newPro = promise.resolve(‘i am not a promise’);

newPro.then(function(str){
console.log(str) // 输出 i am not a promise
})
②如果 obj 本就是一个 Promise 对象,则 promise.resolve 会将 obj 直接返回。
promise.reject
promise.reject 方法与 promise.resolve 一样,能将一个对象转换成 promise 对象,但返回的 promise 对象的状态为 rejected。
async/await
async 是关键词,在一个函数名之前加上该关键词,表明该函数内部有异步操作,而这异步操作应该返回一个 promise 对象,并且在这异步操作之前添加 await 关键词。当函数执行的时候,遇到 await 则会先进行 Promise 的逻辑处理,带 promise 的状态不再为 pending 时再执行该函数后面的语句。
let pro = new Promise(function(resolve, reject){
// 异步处理逻辑
resolve();
})

async function asyncFunc(){
// 正常执行的语句
await pro;
// 等待 promise 处理完之后再执行的语句
}

asyncFunc();
总结
promise 的出现,为我们编写异步函数定下不少规则,在优化我们代码的同时也能减少代码量,并增强可读性,但也需严格遵守 promise/A+ 的规范进行 promise 的开发。

退出移动版