// author: xiang
// date: 2020-08-07
var PENDING = 'pending'
var FULFILLED = 'fulfilled'
var REJECTED = 'rejected'
var NOOP = function(){}
var asyncSetTimer = typeof setImmediate !== 'undefined' ? setImmediate : setTimeout;
function resolve(value) {
if (this._state === PENDING) {
this._state = FULFILLED
this._data = value
asyncCall.call(this)
}
}
function reject(reason) {
if (this._state === PENDING) {
this._state = REJECTED
this._data = reason
asyncCall.call(this)
}
}
function invokeResolver(resolver) {
try {
resolver(resolve.bind(this), reject.bind(this))
} catch (e) {
reject.call(this, e)
}
}
function invokeCallback(subscriber) {
var owner = subscriber.owner
var state = owner._state
var value = owner._data
var callback = subscriber[state]
var promise = subscriber.then
try {
value = callback(value)
resolve.call(promise, value)
} catch(e) {
reject.call(promise, e)
}
}
function asyncCall() {
asyncSetTimer(asyncFlush.bind(this), 0);
}
function asyncFlush() {
var callbacks = this._then
for (let i = 0, len = callbacks.length; i < len; i++) {
invokeCallback(callbacks[i])
}
}
function promise(resolver) {
if (!(this instanceof promise)) {
throw new TypeError("Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.")
}
if (typeof resolver !== "function") {
throw new TypeError("promise resolver is not function")
}
this._then = []
invokeResolver.call(this, resolver)
}
promise.prototype = {
constructor: promise,
_then: null,
_state: PENDING,
_data: null,
then(onFulfillment, onRejection) {
var subscriber = {
owner: this,
then: new this.constructor(NOOP),
fulfilled: onFulfillment,
rejected: onRejection
}
if (this._state === FULFILLED || this._state === REJECTED) asyncFlush.call(this)
this._then.push(subscriber)
return subscriber.then
},
catch(onRejection) {
return this.then(null, onRejection)
}
}
promise.all = function(promises) {
if (!Array.isArray(promises)) {
throw new TypeError("promises is not iterable")
}
return new this(function(resolve, reject) {
var results = []
var remaining = 0
var prom = null
function resolver(index) {
remaining++
return function(value) {
results[index] = value
if (!--remaining) resolve(results)
}
}
for (let i = 0, len = promises.length; i < len; i++) {
prom = promises[i]
if (prom && typeof prom.then === "function") {
prom.then(resolver(i), reject)
} else {
results[i] = prom
}
}
if (!remaining) resolve(results)
})
}
promise.race = function(promises) {
if (!Array.isArray(promises)) {
throw new TypeError("promises is not iterable")
}
return new this(function(resolve, reject) {
var prom = null
for (let i = 0, len = promises.length; i < len; i++) {
prom = promises[i]
if (prom && typeof prom.then === "function") {
prom.then(resolve, reject)
} else {
resolve(prom)
}
}
})
}
promise.resolve = function(value) {
return new this(function(resolve) {
resolve(value)
})
}
promise.reject = function(reason) {
return new this(function(resolve, reject) {
reject(reason)
})
}
实现一个简单的Promise
admin
2020-08-07 00:47:51 阅读 4437关于作者
admin
admin@ifront.net
获得点赞 173
文章阅读量 229719
文章标签