Promise 是什么
Promise 是一种异步编程解决方案。(还有 Generator 也是)
为什么要用 Promise
异步逻辑需要写在回调函数中,使用 promise 可以以链式调用的方式处理异步逻辑
原理
收集回调函数,按顺序调用
使用方式
const mockAjax = (url, s, callback) => {
setTimeout(() => {
callback(url + '异步请求耗时' + s + '秒');
}, 1000 * s)
}
const pUserId = new Promise(resolve => {
mockAjax('getUserId', 1, function (result) {
resolve(result);
})
})
const pUserName = new Promise(resolve => {
mockAjax('getUserName', 2, function (result) {
resolve(result);
})
})
pUserId.then(id => {
console.log(id)
return pUserName
}).then(name => {
console.log(name)
}).catch(error => {
console.log('b', error);
}).finally({ 'a': 5 })
简单实现
class Promise {
state = 'pendding' // 这里相当于在 constructor 中写 this.state = 'pendding'
value = null
callbacks = []
constructor(fn) {
fn(this._resolve.bind(this), this._reject.bind(this))
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({onFulfilled, onRejected, resolve, reject})
})
}
_resolve(value) {
value instanceOf Promise
? value.then.call(value, this._resolve.bind(this), this._reject.bind(this))
: this._changeState('fulfilled', value)
}
_reject(value) {
this._changeState('rejected', value)
}
_changeState(state, value) {
this.state = state
this.value = value
this.callbacks.forEach(callback => this._handle(callback))
}
_handle(callback) {
const dict = {
'pendding': () => this.callbacks.push(callback),
'fulfilled': callback.onFulfilled
? callback.resolve(callback.onFulfilled(this.value))
: callback.resolve(this.value),
'rejected': callback.onRejected
? callback.reject(callback.onRejected(this.value))
: callback.reject(this.value),
}
dict[this.state]()
}
}
补充静态方法
class Promise {
state = 'pendding'
value = null
callbacks = []
constructor(fn) {
fn(this._resolve.bind(this), this._reject.bind(this))
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({onFulfilled, onRejected, resolve, reject})
})
}
catch(onError) {
return this.then(null, onError);
}
finally(onDone) {
if (typeof onDone !== 'function') { return this.then() }
return this.then(onDone, onDone)
}
_resolve(value) {
value instanceOf Promise
? value.then.call(value, this._resolve.bind(this), this._reject.bind(this))
: this._changeState('fulfilled', value)
}
_reject(value) {
this._changeState('rejected', value)
}
_changeState(state, value) {
this.state = state
this.value = value
this.callbacks.forEach(callback => this._handle(callback))
}
_handle(callback) {
const dict = {
'pendding': () => this.callbacks.push(callback),
'fulfilled': callback.onFulfilled
? callback.resolve(callback.onFulfilled(this.value))
: callback.resolve(this.value),
'rejected': callback.onRejected
? callback.reject(callback.onRejected(this.value))
: callback.reject(this.value),
}
dict[this.state]()
}
static resolve(value) {
if(!value) { return new Promise((resolve) => { resolve() }) }
if(value instanceOf Promise) { return value }
if(typeof value === 'object' && typeof value.then === 'function') {
return new Promise((resolve) => { value.then(resolve) })
}
return new Promise((resolve) => { resolve(value) })
}
static reject(value) {
if(typeof value === 'object' && typeof value.then === 'function') {
return new Promise((resolve, reject) => { value.then(reject) })
}
return new Promise((resolve, reject) => { reject(value) })
}
static all(promises) {
return new Promise((resolve, reject) => {
promises.reduce((acc, cur, idx, src) => {
Promise.resolve(cur).then((result)=>{
acc[idx] = result
src.length === acc.length && resolve(acc)
},(err) => { reject(err) })
return acc
}, [])
})
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise) => {
Promise.resolve(promise).then(
(result) => { resolve(result) },
(err) => { reject(err) },
)
})
})
}
}