Promise/A+规范
- new Promise时,需要传递一个 executor 执行器,执行器立刻执行
- executor 接受两个参数,分别是 resolve 和 reject
- promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled
- promise 的状态一旦确认,就不会再改变
- promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, 和 promise 失败的回调 onRejected
- 如果调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值作为参数传递进去。
- 如果promise已经失败,那么执行 onRejected, 并将 promise 失败的原因作为参数传递进去。
- 如果promise的状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次将对应的函数执行(发布订阅)
- then 的参数 onFulfilled 和 onRejected 可以缺省
- promise 可以then多次,promise 的then 方法返回一个 promise
- 如果 then 返回的是一个结果,那么就会把这个结果作为参数,传递给下一个then的成功的回调(onFulfilled)
- 如果 then 中抛出了异常,那么就会把这个异常作为参数,传递给下一个then的失败的回调(onRejected)
11.如果 then 返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功,就走下一个then的成功,如果失败,就走下一个then的失败
A+下的基本功能实现
(function () {
const PENDING = 'pending'
const RESOLVED = 'fulfilled'
const REJECTED = 'rejected'
function Promise(executor) {
const self = this
self.status = PENDING
self.data = undefined
self.callbacks = []
function resolve(value) {
if (self.status === PENDING) {
self.status = RESOLVED
self.data = value
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value)
})
}, 0);
}
}
}
function reject(reason) {
if (self.status === PENDING) {
self.status = REJECTED
self.data = reason
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach(callbacksObj => {
callbacksObj.onRejected(reason)
})
}, 0);
}
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
onResolved = typeof onResolved === 'function' ? onResolved : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
return new Promise((resolve, reject) => {
if (self.status === RESOLVED) {
setTimeout(() => {
const value = onResolved(self.data)
resolve(value)
}, 0);
} else if (self.status === REJECTED) {
setTimeout(() => {
const reason = onRejected(self.data)
reject(reason)
}, 0);
} else {
self.callbacks.push({
onResolved(value) {
resolve(value)
},
onRejected(reason) {
reject(reason)
}
})
}
})
}
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
Promise.all = function (promises) {
if (!(promises instanceof Array)) {
return Promise.reject(new Error('params must be a Array!'))
}
const result = new Array(promises.length)
let count = 0
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
Promise.resolve(p).then(value => {
count++
result[index] = value
if (resultCount === promises.length) {
resolve(resul)
}
}, reason => {
reject(reason)
})
})
})
}
Promise.race = function (promises) {
if (!(promises instanceof Array)) {
return Promise.reject(new Error('params must be a Array!'))
}
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
Promise.resolve(p).then(value => {
resolve(value)
}, reason => {
reject(reason)
})
})
})
}
window.Promise = Promise
})(window)