在开发web前端应用的时候,经常会碰到回调地狱,promise是一个很好的解决办法,基本上所有的浏览器都自行实现了promise对象,但是我想自己实现一个简单的promise then链,然后在网上看到了这篇博文的实现方式,研究许久才明白其运行方式,遂写个博文做个记录以备后日不时之需(代码为上述网站提供的代码,在此仅供参考学习之用)
代码:
/********************
*Promise构造函数接收一个异步处理的函数fn为参数,
*fn接收一个resolve函数和一个reject函数为参数
*fn运行成功则运行resolve,否则运行reject
*resolve,reject都可接受一个参数,运行完毕后Promise.then的参数callback
*Promise.then为promise的一个属性,是一个带callback函数作为参数的函数
*Promise.then应该返回一个新的promise,其fn应为返回这一次的done函数的匿名函数
********************/
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function MyPromise(fn) {
// store state which can be PENDING, FULFILLED or REJECTED
var state = PENDING;
// store value once FULFILLED or REJECTED
var value = null;
// store sucess & failure handlers
var handlers = [];
function fulfill(result) {
state = FULFILLED;
value = result;
handlers.forEach(handle);
handlers = [];
}
function reject(error) {
state = REJECTED;
value = error;
handlers.forEach(handle);
handlers = [];
}
function resolve(result) {
try {
var then = getThen(result);
if (then) {
doResolve(then.bind(result), resolve, reject)
return
}
fulfill(result);
} catch (e) {
reject(e);
}
}
function handle(handler) {
if (state === PENDING) {
handlers.push(handler);
} else {
if (state === FULFILLED &&
typeof handler.onFulfilled === 'function') {
handler.onFulfilled(value);
}
if (state === REJECTED &&
typeof handler.onRejected === 'function') {
handler.onRejected(value);
}
}
}
this.done = function (onFulfilled, onRejected) {
// ensure we are always asynchronous
// setTimeout(function () {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
// }, 0);
}
doResolve(fn, resolve, reject);
this.then = function(onFulfilled, onRejected) {
var self = this;
return new MyPromise(function(resolve, reject) {
self.done(function(result) {
console.log(7);
if (typeof onFulfilled === 'function') {
try {
resolve(onFulfilled(result));
} catch (ex) {
reject(ex);
}
} else {
resolve(result);
}
}, function (error) {
if (typeof onRejected === 'function') {
try {
resolve(onRejected(error));
} catch (ex) {
reject(ex);
}
} else {
reject(error);
}
});
});
}
}
function getThen(value) {
var t = typeof value;
if (value && (t === 'object' || t === 'function')) {
var then = value.then;
if (typeof then === 'function') {
return then;
}
}
return null;
}
function doResolve(fn, onFulfilled, onRejected) {
var done = false;
try {
fn(function (value) {
if (done) return
done = true
onFulfilled(value)
}, function (reason) {
if (done) return
done = true
onRejected(reason)
})
} catch (ex) {
if (done) return
done = true
onRejected(ex)
}
}