上文有提到标准 Promise 的一些特性,接下来一块儿来实现 Promise 的链式调用。
来看看标准 Promise 的链式调用:javascript
var fn = new Promise(function (resolve, reject) {
setTimeout(function() {
resolve('oook~')
}, 500)
})
fn.then(function(data) {
console.log('data-1: ', data)
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject('不oook~')
}, 1000)
})
}, function(err) {
console.log('err-1: ', err)
})
.then(function(data) {
console.log('data-2:', data)
}, function(err) {
console.log('err-2: ', err)
})
.then(function(data) {
console.log('data-3:', data)
}, function(err) {
console.log('err-3: ', err)
})
复制代码
Promise.prototype.then = function (onFulfilled, onRejected) {
var _this = this
// 定义一个promise2变量(别问我为何这么命名,A+规范里就是这么命名的)
var promise2
if (_this.status === 'fulfilled') {
// 返回一个新的promise
promise2 = new Promise(function (resolve, reject) {
// A+ 规范规定,onFulfilled 和 onRejected 都须要异步执行,因此加上一个定时器
setTimeout(function() {
try {
// x多是个普通值,也多是个promise
var x = onFulfilled(_this.successVal)
// x也多是第三方的 Promise 库,用一个函数统一来处理
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
});
}
if (_this.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function() {
try {
var x = onRejected(_this.failVal)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
// 当调用then时,若是是异步操做,就会处于pending状态
if (_this.status === 'pending') {
// 将成功的回调添加到数组中
promise2 = new Promise(function (resolve, reject) {
_this.onFulfilledList.push(function () {
// 能够看到,咱们在每个 resolve 和 reject 执行的地方都加上了异步
setTimeout(function() {
try {
var x = onFulfilled(_this.successVal)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
_this.onRejectedList.push(function () {
setTimeout(function() {
try {
var x = onRejected(_this.failVal)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
})
}
return promise2
}
function resolvePromise(p2, x, resolve, reject) {
// 不能返回本身
if (p2 === x) {
return reject(new TypeError('不能循环引用!'))
}
// 上一篇有说过,resolve 和 reject 不能同时执行,因此用一个锁来当开关
var called
// x返回的多是对象和函数也多是一个普通的值
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
var then = x.then
if (typeof then === 'function') {
then.call(x, function (y) {
// ------- resolve 和 reject 不能同时执行 -------
if (called) {
return
}
called = true
// 若是成功的话,y有可能也是个 promise,因此递归继续解析
resolvePromise(p2, y, resolve, reject)
}, function (e) {
// ------- resolve 和 reject 不能同时执行 -------
if (called) {
return
}
called = true
reject(e)
})
} else {
// 若是是普通值,直接返回成功
resolve(x)
}
} catch(e) {
if (called) {
return
}
called = true
reject(e)
}
} else {
resolve(x)
}
}
复制代码
var p = new Promise(function(resolve, reject){
setTimeout(function() {
resolve('彻底ooooook~')
}, 500)
})
p.then(function (data) {
console.log('success1: ', data)
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject('啊啊啊啊啊啊啊啊啊')
}, 1000)
})
}, function (err) {
console.log('failed: ', err)
})
.then(function (data) {
console.log('success2: ', data)
}, function(err) {
console.log('failed2: ', err)
})
复制代码
结果以下: java
结果彻底ooooook啊啊啊啊啊啊数组