class Promise2 {
#status = 'pending'
constructor(fn){
this.q = []
const resolve = (data)=>{
this.#status = 'fulfilled'
const f1f2 = this.q.shift()
if(!f1f2 || !f1f2[0]) return
const x = f1f2[0].call(undefined, data)
if(x instanceof Promise2) {
x.then((data)=>{
resolve(data)
}, (reason)=>{
reject(reason)
})
}else {
resolve(x)
}
}
const reject = (reason)=>{
this.#status = 'rejected'
const f1f2 = this.q.shift()
if(!f1f2 || !f1f2[1]) return
const x = f1f2[1].call(undefined, reason)
if(x instanceof Promise2){
x.then((data)=>{
resolve(data)
}, (reason)=>{
reject(reason)
})
}else{
resolve(x)
}
}
fn.call(undefined, resolve, reject)
}
then(f1, f2){
this.q.push([f1, f2])
}
}
const p = new Promise2(function(resolve, reject){
setTimeout(function(){
reject('出错')
},3000)
})
p.then( (data)=>{console.log(data)}, (r)=>{console.error(r)} )
Promise是异步编程的一种解决方案,比传统的回调函数要更方便,合理,避免了回调地狱。
Promise对象只有三种状态:进行中,已成功,已失败。一个Promise对象代表了一个异步操作。这个状态只能改变一次。进行中->成功,进行中->失败。
用法:new Promise创建一个promise实例,Promsie构造函数接受一个函数作为参数。这个函数的两个参数分别是resolve和reject,它们也是函数。resolve函数会在异步操作成功后被调用,把异步操作的结果作为参数传递出去;reject函数会在异步操作失败后被调用,把错误的信息作为参数传递出去。
创建了promise实例后,通过then方法给状态变化时添加回调函数。then接受两个回调函数作为参数,第一个是状态变为resolve时被调用,第二个状态变为reject被调用。
Promise.all: 接收多个promise实例作为参数,包装成一个新的promise实例const p = Promise.all([p1, p2, p3]);p的状态由p1、p2、p3决定,分成两种情况。
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
Promise.race: 同样是将多个 Promise 实例,包装成一个新的 Promise 实例.const p = Promise.race([p1, p2, p3]);只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。