【JavaScript由浅入深】详解Promise
文章目录
一、ES5处理异步任务
使用回调函数实现异步任务
- 我们调用一个函数,等待一段时间后,将传入的数字进行累加;
- 如果传入的数字符合要求,那么告知执行成功,并且将相关数据返回过去;
- 如果传入的数字不符合要求,那么告知执行失败,并且告知错误信息
// 1.设计函数
function fn(counter, successCallback, failureCallback) {
//异步任务
setTimeout(() => {
if(counter>0) {
let sum =0
for(let i =0;i<counter;i++) {
sum += i
}
//在某一时刻只需要回调传入的函数
//成功情况
successCallback(sum)
} else {
// 失败情况
failureCallback(`${counter}值错误`)
}
}, 2000)
}
fn(94, (value) => {
console.log("本次执行成功了:", value)
},(err) => {
console.log("本次执行失败了:", err);
})
弊端:
- 我们需要自己来设计回调函数、回调函数的名称、回调函数的使用等;
- 对于不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐心去看别人的源码或者文档,以便可以理解它这个函数到底怎么用
二、Promise
2.1 什么是Promise?
- Promise是一个类
- 当我们需要的时候,给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象;
一个
Promise
对象代表一个在这个 promise 被创建出来时不一定已知值的代理。它让你能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
- 在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor
new Promise(executor)
- 这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject;
- 当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数;
- 当我们调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数;
一个 Promise
必然处于以下几种状态之一:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled):意味着操作成功完成。
- 已拒绝(rejected):意味着操作失败。
2.2 Promise的使用方法
const promise = new Promise((resolve, reject) => {
resolve(value) //该函数执行时会回调onFulfilled
// reject(reason) //该函数执行时会回调onRejected
console.log("hello world") //该回调函数会被立即执行
})
// 监听promise对象的状态 方式一
promise.then(onFulfilled).catch(onRejected)
// 监听promise对象的状态 方式二
promise.then(onFulfilled, onRejected)
使用Promise,将之前的代码进行重构:
// 1.设计函数
function fn(counter) {
const promise = new Promise((resolve, reject) => {
// 异步任务
setTimeout(() => {
if (counter > 0) {
let sum = 0
for (let i = 0; i < counter; i++) {
sum += i
}
// 成功的回调
resolve(sum)
} else {
// 失败的回调
reject(`${counter}值错误`)
}
}, 2000)
})
return promise
}
fn(59).then(value => {
console.log("执行成功", value)
}).catch(err => {
console.log("执行失败", err)
})
三、Promise的类方法与实例方法
3.1 类方法
- all()
- 接受⼀个数组作为参数,数组元素是promise对象,返回⼀个新的promise对象
- 可以不是数组,但必须是可迭代对象,且返回的每⼀个成员都是Promise实例
- 只有数组⾥所以的promise对象都是fulfilled状态时,返回的promsie的状态是fulfilled
- 当数组中的promise对象有⼀个的rejected状态时,返回的promise的状态时rejected
- race()
- 接受⼀个数组作为参数,数组元素是promise对象,返回⼀个新的promise对象
- 只要数组中的实例有⼀个率先改变,返回的promise对象就跟着改变
- allSettled()
- 接受⼀个数组作为参数,数组元素是promise对象,返回⼀个新的promise对象
- 只有等数组中所有的promise对象都发⽣状态改变后,返回的promsie对象状态才会改变
- 返回的promsie对象,⼀旦状态发⽣改变,状态总是fulfilled
- any()
- 接受⼀个数组作为参数,数组元素是promise对象,返回⼀个新的promise对象
- 只要数组实例中有⼀个变成fulfilled状态,返回的promise对象就会变成fulfilled状态
- 只有当数组中所有的promise实例都变成rejected状态,返回的promise 对象才变成 rejected状态
- resolve()
- 静态方法
Promise.resolve
返回一个解析过的Promise
对象
- 静态方法
- rejected()
- 返回⼀个新的promsie实例,该实例的状态未为rejected
3.2 实例方法
3.2.1 then()、catch()
- then(onFulfilled[, onRejected])
- onFulfilled ---->成功时的回调函数
- nRejected ----> 失败时的回调函数
- 返回值是⼀个新的promise对象,promise⽀持链式调⽤的原因
举个栗子:
new Promise((resolve, reject) => {
// resolve("执行成功")
reject("执行失败")
}).then(value => {
console.log(value)
}, reason => {
console.log(reason)
})
- catch(onRejected)
- onRejected ---->失败时的回调
3.2.2 finally()
- finally(callback)
- callback ---->不管promise最后的状态,在执⾏完then或catch指定的回调函数后,都会执行的回调
举个栗子:
执行如下代码:
const p1 = new Promise((resolve, reject) => {
resolve("执行成功")
// reject("执行失败")
})
p1.then(res => {
console.log("res:", res)
}).catch(err => {
console.log("err:", err)
}).finally(() => {
console.log("finally")
})
不论是成功还是失败,都会执行finally
三、Promise构造函数的参数—Executor
3.1 Executor
- Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:
new Promise((resolve, reject) => {
console.log("executor")
})
- 通常我们会在Executor中确定我们的Promise状态:
- 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved);
- 通过reject,可以拒绝(reject)Promise的状态;
- 这里需要注意:一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的
- 在我们调用resolve的时候,如果resolve传入的值本身不是一个Promise,那么会将该Promise的状态变成兑现(fulfilled);
- 在之后我们去调用reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);
3.2 resolve不同值
- 如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数;
new Promise((resolve, reject) => {
resolve("normal resolve")
}).then(res => {
console.log("res", res)
})
- 如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态:
new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
setTimeout(() => {
resolve("第二个Promise的resolve")
// reject("第二个Promise的reject")
}, 2000);
}))
}).then (res => {
console.log("res:", res)
}).catch(err => {
console.log("err:". err)
})
- 如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据then方法的结 果来决定Promise的状态
new Promise((resolve, reject) => {
resolve({
then: function (resolve, reject) {
resolve("thenable value")
}
})
}).then(res => {
console.log(res)
})
🎉写在最后
✨ 创作不易,希望各位大佬支持一下