在Javascript中做異步處理時奶稠,我們通常都要用到Promise。各大Javascript庫中都有Promise的實(shí)現(xiàn)捡遍,例如JQuery和Dojo等窒典。Javascript也有標(biāo)準(zhǔn)的Promise的定義,不過不幸的是IE不支持標(biāo)準(zhǔn)的Promise稽莉。下面是對標(biāo)準(zhǔn)Promise的說明文檔:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
在有些情況下瀑志,如果我們不愿用到已有的Javascript庫,又想使用Promise來做異步處理污秆,那就需要自己實(shí)現(xiàn)一個Promise劈猪,特別是在IE上需要。另外良拼,很多面試都會問到這樣的問題战得,如何自己實(shí)現(xiàn)一個Promise。下面我做了一個簡單的實(shí)現(xiàn)庸推,代碼很簡單常侦,但是基本功能已經(jīng)具備了,稍作完善就可以在產(chǎn)品中用了贬媒。
// Promise的構(gòu)造函數(shù)聋亡,傳入的參數(shù)executor實(shí)際上是一個函數(shù),executor的參數(shù)有兩個一個是resolve函數(shù)际乘,一個是reject函數(shù)
function Promise(executor) {????
? ? if(executor && typeof(executor)=='function' ) { // 判斷executor是否是函數(shù)
? ? ? ? executor(this.resolver.bind(this),this.reject.bind(this)); //立即調(diào)用executor坡倔,傳入的參數(shù)是自己的resolver函數(shù),這里需要用bind(this),這樣才能保證調(diào)用resolver時用Promise自己的執(zhí)行環(huán)境
? ? }
}
Promise.prototype.then = function(onFulfilled) {? // then的參數(shù)是一個函數(shù)脖含,當(dāng)我們調(diào)用完resolve之后調(diào)用這個函數(shù)
? ? this.onFulfilled = onFulfilled; //我們需要先保存這個函數(shù)罪塔,以備以后調(diào)用
? ? return new Promise(function(resolver,rejector){ // 這里我們需要返回一個新的Promise,這樣才能實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用
? ? ? ? this.nextResolver = resolver; // 保存resolver以便下次調(diào)用
? ? }.bind(this));
}
Promise.prototype.resolver = function(returnValue) {
? ? if(this.onFulfilled && typeof(this.onFulfilled) == 'function') {
? ? ? ? let newReturnValue = this.onFulfilled(returnValue); // 調(diào)用then傳入的函數(shù)
? ? ? ? if(this.nextResolver) {
? ? ? ? ? ? this.nextResolver(newReturnValue); //如果有鏈?zhǔn)秸{(diào)用养葵,繼續(xù)調(diào)用下一個resolve
? ? ? ? }
? ? }
}
Promise.prototype.reject = function(error) {
? ? if(this.onRejected && typeof(this.onRejected) == 'function') {
? ? ? ? this.onRejected(error);
? ? }
}
我們再通過以下的使用來驗(yàn)證我們實(shí)現(xiàn)的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);
});