構造 Promise
現在我們構造一個promise物件:
new Promise(function (resolve,reject)) {
//要做的事情...
}
透過新建一個Promise 物件好像並沒有看出它怎樣“更加優雅地書寫複雜的非同步任務”。我們之前遇到的非同步任務都是一次非同步,如果需要多次呼叫非同步函式呢?例如,如果我想分三次輸出字串,第一次間隔1秒,第二次間隔4秒,第三次間隔3秒:
例項
setTimeout(function(){
console.log("First");
setTimeout(function (){
console.1og("Second");
setTimeout(function(){
console.log("Third");
},3000);
},4000);
},1000);
使用延遲函式固然可以實現這個功能,但是在一個複雜的程式中,使用函式瀑布實現程式是一件特別繁瑣的事情。
我們現在使用Promise來實現:
例項
new Promise(function(resolve, reject){
setTimeout(function (){
console.log("First");
resolve();
},1000);
}).then(function(){
return new Promise(function(resolve,reject)
setTimeout(function (){
console.1og("Second");
resolve();
},4000);
});
}).then(function(){
setTimeout(function (){
console.1og("Third");
},3000);
});
Promise的使用
Promise 建構函式只有一個引數,是一個函式,這個函式在構造之後會直接被非同步執行,所以我們稱之為起始函式。起始函式包含兩個引數resolve和 reject。
當Promise 被構造時,起始函式會被非同步執行:
例項
new Promise(function(resolve, reject){
console.1og("Run"); 3});
這段程式會直接輸出 Run。
resolve 和 reject 都是函式,其中呼叫 resolve 代 表一切正常,reject是出現異常時所呼叫的:
例項
new Promise(function(resolve, reject){
var a=0;
var b=1;
if (b ==θ)reject("Divide zero");
else resolve(a / b);
}).then(function(value){
console.log("a/b="+value);
}).catch(function(err){
console.log(err);
}).finally(function(){
console.log("End");
});
這段程式執行結果是:
1 a/b-0
2 End
Promise 類有 .then().catch()和.finally()三個方 法,這三個方法的引數都是一個函式,then()可以將引數中的函式新增到當前Promise的正常執行序列,catch()則是設定Promise的異常處理序列,finally()是在Promise 執行的最後一定會執 行的序列。.then()傳入的函式會按順序依次執行,有任何異常都會直接跳到catch序列:
例項
new Promise(function(resolve, reject){
console.log(1111);
resolve(2222);
}).then(function (value){
console.1og(value);
return 3333;
}).then(function(value){
console.log(value);
throw "An error";
}).catch(function(err){
console.log(err);
});
執行結果:
1 1111
2 2222
3 3333
4 An error
resolve()中可以放置一個引數用於向下一個then傳遞一個值,then中的函式也可以返回一個值傳遞給 then。但是,如果then中返回的是一個Promise 物件,那麼下一個 then 將相當於對這個返回的Promise 進行操作,這一點從剛才的計時器的例子中可以看出來。
reject()引數中一般會傳遞一個異常給之後的catch函式用於處理異常。
但是請注意以下兩點:
- resolve 和 reject的作用域只有起始函式,不包括then以及其他序列;
- resolve 和 reject 並不能夠使起始函式停止執行,別忘了return。
Promise 函式
上述的“計時器”程式看上去比函式瀑布還要長,所以我們可以將它的核心部分寫成一個Promise函式:
例項 :
function print(delay,message){
return new Promise(function (resolve, reject){
setTimeout(function(){
console.log(message);
resolve();
},delay);
});
}
然後我們就可以放心大膽的實現程式功能了:
例項
print(1000,"First").then(function (){
return print(4000,"Second");
}).then(function(){
print(3000,"Third");
})
這種返回值為一個 Promise 物件的函式稱作Promise 函式,它常常用於開發基於非同步操作的庫。