ES6-Promise物件
1 是什麼
先直接上圖,列印一下Promise物件,觀察下Promise是什麼
console.dir(Promise)
可以知道,Promise是一個建構函式,有著reject、resolve函式。prototype有then、catch等方法,說明了只要是Promise物件都會有這兩個方法。
Promise建構函式是傳入一個函式
2 怎麼用
var promise = new Promise((resolve, reject) => {
setTimeout(function () {
console.log('執行完成' );
resolve('隨便什麼資料');
}, 2000);
});
result:
執行完成
傳入的函式有兩個引數:resolve、reject,分別表示非同步操作執行成功後的回撥函式和非同步操作失敗後的回撥函式。其實這裡用“成功”和“失敗”來描述並不準確,按照標準來講,resolve是將Promise的狀態置為fullfiled,reject是將Promise的狀態置為rejected。不過在我們開始階段可以先這麼理解,後面再細究概念。
執行以上程式碼,發現promise並沒有呼叫,只是new了一個Promise,對應的傳入函式的程式碼就已經執行了。因此,我們通常都是把Promise包在一個函式中,在需要的時候才去執行這個函式,如:
function f() {
var promise = new Promise((resolve, reject) => {
setTimeout(function () {
console.log('執行完成');
resolve('隨便什麼資料');
}, 2000);
});
return promise
}
f()
result:
執行完成
這時引出兩個問題。為什麼需要大費周章的包裝這樣的一個函式?resolve有什麼用?
2.1 為什麼需要引入
f().then (function(data){
console.log(data);
//後面可以用傳過來的資料做些其他操作
//......
});
在f()的返回上可以直接呼叫then方法,then接收一個引數,是函式,並且會拿到我們在f中呼叫resolve時傳入的引數。執行這段程式碼,會在2秒後輸出“執行完成”,緊接著輸出“隨便什麼資料”。
這時,我們恍然大悟了,原來then呼叫的function相當於我們之前寫的回撥函式,相當於是這種形式:
function runAsync(callback){
setTimeout(function(){
console.log('執行完成');
callback('隨便什麼資料');
}, 2000);
}
runAsync(function(data){
console.log(data);
});
那使用Promise有什麼好處呢?我們不妨考慮一個問題,如果callback函式也是一個非同步操作,而且執行完後也需要有相應的回撥函式,可能會變成 runAsync(function(data,function(data){}){…})。看起來十分醜陋,假如使用Promise程式碼就不會這麼醜陋了~
Promise的優勢在於,可以在then方法中繼續寫Promise物件並返回,然後繼續呼叫then來進行回撥操作。
2.2 鏈式操作的用法
所以,從表面上看,Promise只是能夠簡化層層回撥的寫法,而實質上,Promise的精髓是“狀態”,用維護狀態、傳遞狀態的方式來使得回撥函式能夠及時呼叫,它比傳遞callback函式要簡單、靈活的多。所以使用Promise的正確場景是這樣的:
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return runAsync3();
})
.then(function(data){
console.log(data);
});
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些非同步操作
setTimeout(function(){
console.log('非同步任務1執行完成');
resolve('隨便什麼資料1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些非同步操作
setTimeout(function(){
console.log('非同步任務2執行完成');
resolve('隨便什麼資料2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些非同步操作
setTimeout(function(){
console.log('非同步任務3執行完成');
resolve('隨便什麼資料3');
}, 2000);
});
return p;
}
result:
非同步任務1執行完成
隨便什麼資料1
非同步任務2執行完成
隨便什麼資料2
非同步任務3執行完成
隨便什麼資料3
我們可以通過鏈式程式設計避免了包含多函式回撥的情況,當然並不是都需要return Promise物件,你也可以返回其他資料型別,在後面的then中就能直接直接接收到資料了,比如:
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return '直接返回資料'; //這裡直接返回資料
})
.then(function(data){
console.log(data);
});
result:
非同步任務1執行完成
隨便什麼資料1
非同步任務2執行完成
隨便什麼資料2
直接返回資料
2.3 reject用法
前面我們一直都是使用resolve函式,並沒有使用reject函式。resolve函式是表示了“執行成功”的回撥,reject函式表示“執行失敗”的函式。
function runAsync1() {
var p = new Promise(function (resolve, reject) {
//做一些非同步操作
setTimeout(function () {
console.log('非同步任務1執行完成');
// resolve('隨便什麼資料1');
reject("error")
}, 1000);
});
return p;
}
runAsync1().then((data) => {
console.log('resolve');
console.log(data)
}, (error, data) => {
console.log('rejected');
console.log(error)
})
result:
非同步任務1執行完成
rejected
error
需要注意的是,只要執行reject或者resolve,後面的就不會執行了,如:
function runAsync1() {
var p = new Promise(function (resolve, reject) {
//做一些非同步操作
setTimeout(function () {
console.log('非同步任務1執行完成');
resolve('隨便什麼資料1');
reject("error")
}, 1000);
});
return p;
}
因為resolve在reject的前面,所以只會執行resolve,不會執行reject。
3 總結
- Promise是一個物件
- 引入是為了消除多重回調函式
- Promise還有很多方法沒有介紹(catch、finally、success、fail)
參考文獻
ECMAScript6入門
大白話講解Promise(一)
ECMAScript6入門
廣州蘆葦科技Java開發團隊
蘆葦科技-廣州專業軟體外包服務公司
提供微信小程式、APP應用研發、UI設計等專業服務,專注於網際網路產品諮詢、品牌設計、技術研發等領域
訪問 www.talkmoney.cn 瞭解更多
萬能說明書 | 早起日記Lite | 凹凸桌布 | 言財