promise使用场景
-
promise
是promise A+
规范的实现,promise A+
点这里了解 -
最常用的是封装
axios
请求
function get(url, params) {
return new Promise((resolve, reject) => {
axios
.get(url, {
params: params
})
.then(res => {
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
判断一个对象是否为promise
promise
是一个对象或者函数,有一个then
方法
function isObject(){
return obj !== null && typeof obj === 'object'
}
function isFunction(){
return obj !== null && typeof obj === 'function'
}
function isPromise(val) {
return isObject(val) && isFunction(val.then) && isFunction(val.catch);
}
第一步,同步
class myPromise {
#state = 'pending';
#result = undefined;
constructor(exe) {
try {
exe(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(data) {
if (this.#state != 'pending') return
this.#state = 'resolved'
this.#result = data
}
reject(data) {
if (this.#state != 'pending') return
this.#state = 'rejected'
this.#result = data
}
then(onFulled, onRejected) {
if (this.#state == 'resolved') {
onFulled(this.#result)
}
if (this.#state == 'rejected') {
onRejected(this.#result)
}
}
}
- 同步测试结果,正确打印1
const p1 = new myPromise((resolve, reject) => {
resolve('1');
}).then(res => {
console.log(res)
})
- 异步测试结果,无报错,无打印
const p1 = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('1');
}, 1000)
}).then(res => {
console.log(res)
})
第二步,同步+异步
-
异步的时候,then函数里面状态还是pending,代码需要修改修改
-
异步的时候,收集需要执行的函数,在状态改变后执行收集的函数,(发布 - 订阅)
-
代码修改之后,同步异步都正常了
class myPromise {
#state = 'pending';
#result = undefined;
#resolveCB = [];
#rejectCB = [];
constructor(exe) {
try {
exe(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(data) {
if (this.#state != 'pending') return
this.#state = 'resolved'
this.#result = data
this.#resolveCB.forEach(cb => cb(data))
}
reject(data) {
if (this.#state != 'pending') return
this.#state = 'rejected'
this.#result = data
this.#rejectCB.forEach(cb => cb(data))
}
then(onFulled, onRejected) {
// 同步
if (this.#state == 'resolved') {
onFulled(this.#result)
}
if (this.#state == 'rejected') {
onRejected(this.#result)
}
// 异步
if (this.#state == 'pending') {
this.#resolveCB.push(onFulled)
this.#rejectCB.push(onRejected)
}
}
}
第三步 同步+异步+链式调用
-
链式调用有两个地方需要注意
-
一个是返回一个
promise
-
另一个是值的透传,下一个
then
的入参是上一个then
的返回结果 -
then
函数异步那里,push
的是一个函数,这一点很重要,理解了这一点链式调用就明白了
class myPromise {
#state = 'pending';
#result = undefined;
#resolveCB = [];
#rejectCB = [];
constructor(exe) {
try {
exe(this.resolve.bind(this), this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(data) {
if (this.#state != 'pending') return
this.#state = 'resolved'
this.#result = data
this.#resolveCB.forEach(cb => cb(data))
}
reject(data) {
if (this.#state != 'pending') return
this.#state = 'rejected'
this.#result = data
this.#rejectCB.forEach(cb => cb(data))
}
then(onFulled, onRejected) {
return new myPromise((resolve, reject) => {
// 同步
if (this.#state == 'resolved') {
const res = onFulled(this.#result)
this.resolveMyPromise(res, resolve, reject)
}
if (this.#state == 'rejected') {
const err = onRejected(this.#result)
this.resolveMyPromise(err, resolve, reject)
}
// 异步
if (this.#state == 'pending') {
this.#resolveCB.push(() => {
const res = onFulled(this.#result)
this.resolveMyPromise(res, resolve, reject)
resolve(res)
})
this.#rejectCB.push(() => {
const err = onRejected(this.#result)
this.resolveMyPromise(err, resolve, reject)
})
}
})
}
resolveMyPromise(res, resolve, reject) {
if (res instanceof myPromise) {
res.then((val) => resolve(val), (err) => reject(err))
} else {
resolve(res)
}
}
}
第四步 同步+异步+链式调用+all+race
-
all
是等到所有都完成或有一个失败,就返回新的promise
-
race
是有一个完成就返回新的promise
all(arr) {
return new myPromise((resolve, reject) => {
const result = []
for (let i = 0; i < arr.length; i++) {
arr[i].then(val => {
result.push(val)
if (arr.length == result.length) resolve(result)
}, reject)
}
})
}
race(arr) {
return new myPromise((resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
arr[i].then(resolve, reject)
}
})
}
总结
-
promise
手写到这一步,大部分面试官都解决了 -
then
函数是在微任务里面执行的,本文没有如此深入