在Javascript中做异步处理时,我们通常都要用到Promise。各大Javascript库中都有Promise的实现,例如JQuery和Dojo等。Javascript也有标准的Promise的定义,不过不幸的是IE不支持标准的Promise。下面是对标准Promise的说明文档:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
在有些情况下,如果我们不愿用到已有的Javascript库,又想使用Promise来做异步处理,那就需要自己实现一个Promise,特别是在IE上需要。另外,很多面试都会问到这样的问题,如何自己实现一个Promise。下面我做了一个简单的实现,代码很简单,但是基本功能已经具备了,稍作完善就可以在产品中用了。
// Promise的构造函数,传入的参数executor实际上是一个函数,executor的参数有两个一个是resolve函数,一个是reject函数
function Promise(executor) {
if(executor && typeof(executor)=='function' ) { // 判断executor是否是函数
executor(this.resolver.bind(this),this.reject.bind(this)); //立即调用executor,传入的参数是自己的resolver函数,这里需要用bind(this),这样才能保证调用resolver时用Promise自己的执行环境
}
}
Promise.prototype.then = function(onFulfilled) { // then的参数是一个函数,当我们调用完resolve之后调用这个函数
this.onFulfilled = onFulfilled; //我们需要先保存这个函数,以备以后调用
return new Promise(function(resolver,rejector){ // 这里我们需要返回一个新的Promise,这样才能实现链式调用
this.nextResolver = resolver; // 保存resolver以便下次调用
}.bind(this));
}
Promise.prototype.resolver = function(returnValue) {
if(this.onFulfilled && typeof(this.onFulfilled) == 'function') {
let newReturnValue = this.onFulfilled(returnValue); // 调用then传入的函数
if(this.nextResolver) {
this.nextResolver(newReturnValue); //如果有链式调用,继续调用下一个resolve
}
}
}
Promise.prototype.reject = function(error) {
if(this.onRejected && typeof(this.onRejected) == 'function') {
this.onRejected(error);
}
}
我们再通过以下的使用来验证我们实现的Promise。
let myFirstPromise = new Promise((resolve, reject) => {
// We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
// In this example, we use setTimeout(...) to simulate async code.
// In reality, you will probably be using something like XHR or an HTML5 API.
setTimeout(function(){
resolve("Success!"); // Yay! Everything went well!
}, 250);
});
myFirstPromise.then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log("Yay! " + successMessage);
return "Success 2";
}).then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log("Yay2! " + successMessage);
}).then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log("Yay3! " + successMessage);
});