- ES6 教程
- ES6 - 首頁
- ES6 - 概述
- ES6 - 環境
- ES6 - 語法
- ES6 - 變數
- ES6 - 運算子
- ES6 - 決策
- ES6 - 迴圈
- ES6 - 函式
- ES6 - 事件
- ES6 - Cookies
- ES6 - 頁面重定向
- ES6 - 對話方塊
- ES6 - Void 關鍵字
- ES6 - 頁面列印
- ES6 - 物件
- ES6 - 數字
- ES6 - 布林值
- ES6 - 字串
- ES6 - Symbol
- ES6 - 新的字串方法
- ES6 - 陣列
- ES6 - 日期
- ES6 - 數學
- ES6 - 正則表示式
- ES6 - HTML DOM
- ES6 - 迭代器
- ES6 - 集合
- ES6 - 類
- ES6 - Map 和 Set
- ES6 - Promise
- ES6 - 模組
- ES6 - 錯誤處理
- ES6 - 物件擴充套件
- ES6 - Reflect API
- ES6 - Proxy API
- ES6 - 驗證
- ES6 - 動畫
- ES6 - 多媒體
- ES6 - 除錯
- ES6 - 圖片地圖
- ES6 - 瀏覽器
- ES7 - 新特性
- ES8 - 新特性
- ES9 - 新特性
- ES6 有用資源
- ES6 - 快速指南
- ES6 - 有用資源
- ES6 - 討論
ES6 - Promise
Promise 語法
與 Promise 相關的語法如下所示,其中,p 是 Promise 物件,resolve 是 Promise 成功執行時應呼叫的函式,reject 是 Promise 遇到錯誤時應呼叫的函式。
let p = new Promise(function(resolve,reject){
let workDone = true; // some time consuming work
if(workDone){
//invoke resolve function passed
resolve('success promise completed')
}
else{
reject('ERROR , work could not be completed')
}
})
示例
下面給出的示例展示了一個函式 add_positivenos_async(),該函式非同步地新增兩個數字。如果傳遞正值,則 Promise 被 resolved。如果傳遞負值,則 Promise 被 rejected。
<script>
function add_positivenos_async(n1, n2) {
let p = new Promise(function (resolve, reject) {
if (n1 >= 0 && n2 >= 0) {
//do some complex time consuming work
resolve(n1 + n2)
}
else
reject('NOT_Postive_Number_Passed')
})
return p;
}
add_positivenos_async(10, 20)
.then(successHandler) // if promise resolved
.catch(errorHandler);// if promise rejected
add_positivenos_async(-10, -20)
.then(successHandler) // if promise resolved
.catch(errorHandler);// if promise rejected
function errorHandler(err) {
console.log('Handling error', err)
}
function successHandler(result) {
console.log('Handling success', result)
}
console.log('end')
</script>
以上程式碼的輸出將如下所示:
end Handling success 30 Handling error NOT_Postive_Number_Passed
Promise 鏈式呼叫
當我們需要依次執行一系列非同步任務時,可以使用Promise 鏈式呼叫。當一個 Promise 依賴於另一個 Promise 的結果時,就會進行鏈式呼叫。這在下面的示例中顯示
示例
在下面的示例中,add_positivenos_async() 函式非同步地新增兩個數字,如果傳遞負值則被拒絕。當前非同步函式呼叫的結果作為引數傳遞給後續的函式呼叫。注意每個then()方法都有一個返回值。
<script>
function add_positivenos_async(n1, n2) {
let p = new Promise(function (resolve, reject) {
if (n1 >= 0 && n2 >= 0) {
//do some complex time consuming work
resolve(n1 + n2)
}
else
reject('NOT_Postive_Number_Passed')
})
return p;
}
add_positivenos_async(10,20)
.then(function(result){
console.log("first result",result)
return add_positivenos_async(result,result)
}).then(function(result){
console.log("second result",result)
return add_positivenos_async(result,result)
}).then(function(result){
console.log("third result",result)
})
console.log('end')
</script>
以上程式碼的輸出將如下所示:
end first result 30 second result 60 third result 120
下面將詳細討論 Promise 物件的一些常用方法:
promise.all()
此方法可用於聚合多個 Promise 的結果。
語法
promise.all() 方法的語法如下所示,其中,iterable 是一個可迭代物件。例如陣列。
Promise.all(iterable);
示例
下面給出的示例執行了一個非同步運算元組 [add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)]。當所有操作完成後,Promise 將被完全 resolved。
<script>
function add_positivenos_async(n1, n2) {
let p = new Promise(function (resolve, reject) {
if (n1 >= 0 && n2 >= 0) {
//do some complex time consuming work
resolve(n1 + n2)
}
else
reject('NOT_Postive_Number_Passed')
})
return p;
}
//Promise.all(iterable)
Promise.all([add_positivenos_async(10,20),add_positivenos_async(30,40),add_positivenos_async(50,60)])
.then(function(resolveValue){
console.log(resolveValue[0])
console.log(resolveValue[1])
console.log(resolveValue[2])
console.log('all add operations done')
})
.catch(function(err){
console.log('Error',err)
})
console.log('end')
</script>
以上程式碼的輸出如下所示:
end 30 70 110 all add operations done
promise.race()
此函式接受一個 Promise 陣列,並返回第一個已完成的 Promise。
語法
promise.race() 函式的語法如下所示,其中,iterable 是一個可迭代物件。例如陣列。
Promise.race(iterable)
示例
下面給出的示例接受一個非同步運算元組 [add_positivenos_async(10,20),add_positivenos_async(30,40)]。
只要任何一個加法操作完成,Promise 就會被 resolved。Promise 不會等待其他非同步操作完成。
<script>
function add_positivenos_async(n1, n2) {
let p = new Promise(function (resolve, reject) {
if (n1 >= 0 && n2 >= 0) {
//do some complex time consuming work
resolve(n1 + n2)
} else
reject('NOT_Postive_Number_Passed')
})
return p;
}
//Promise.race(iterable)
Promise.race([add_positivenos_async(10,20),add_positivenos_async(30,40)])
.then(function(resolveValue){
console.log('one of them is done')
console.log(resolveValue)
}).catch(function(err){
console.log("Error",err)
})
console.log('end')
</script>
以上程式碼的輸出如下所示:
end one of them is done 30
Promise 是在 JavaScript 中實現非同步程式設計的一種簡潔方法(ES6 新特性)。在 Promise 之前,使用回撥函式來實現非同步程式設計。讓我們首先了解什麼是非同步程式設計及其使用回撥函式的實現。
理解回撥函式
函式可以作為引數傳遞給另一個函式。這種機制稱為回撥函式。回撥函式在事件中很有用。
以下示例將幫助我們更好地理解此概念。
<script>
function notifyAll(fnSms, fnEmail) {
console.log('starting notification process');
fnSms();
fnEmail();
}
notifyAll(function() {
console.log("Sms send ..");
},
function() {
console.log("email send ..");
});
console.log("End of script");
//executes last or blocked by other methods
</script>
在上面顯示的notifyAll()方法中,通知是透過傳送簡訊和傳送電子郵件來實現的。因此,notifyAll 方法的呼叫者必須將兩個函式作為引數傳遞。每個函式承擔一項單一職責,例如傳送簡訊和傳送電子郵件。
成功執行以上程式碼後,將顯示以下輸出。
starting notification process Sms send .. Email send .. End of script
在上面提到的程式碼中,函式呼叫是同步的。這意味著 UI 執行緒將等待整個通知過程完成。同步呼叫會變成阻塞呼叫。現在讓我們瞭解非阻塞或非同步呼叫。
理解非同步回撥函式
考慮以上示例。
要啟用指令碼,請對 notifyAll() 方法執行非同步或非阻塞呼叫。我們將使用 JavaScript 的setTimeout()方法。此方法預設情況下是非同步的。
setTimeout() 方法接受兩個引數:
一個回撥函式。
方法將在多少秒後被呼叫。
在這種情況下,通知過程已使用超時包裝。因此,它將延遲兩秒,由程式碼設定。將呼叫 notifyAll(),並且主執行緒繼續執行其他方法。因此,通知過程不會阻塞主 JavaScript 執行緒。
<script>
function notifyAll(fnSms, fnEmail) {
setTimeout(function() {
console.log('starting notification process');
fnSms();
fnEmail();
}, 2000);
}
notifyAll(function() {
console.log("Sms send ..");
},
function() {
console.log("email send ..");
});
console.log("End of script"); //executes first or not blocked by others
</script>
成功執行以上程式碼後,將顯示以下輸出。
End of script starting notification process Sms send .. Email send ..
如果有多個回撥函式,程式碼看起來會很嚇人。
<script>
setTimeout(function() {
console.log("one");
setTimeout(function() {
console.log("two");
setTimeout(function() {
console.log("three");
}, 1000);
}, 1000);
}, 1000);
</script>
ES6 透過引入 Promise 的概念來解決這個問題。Promise 是“延續事件”,它們可以幫助您以更簡潔的程式碼風格一起執行多個非同步操作。
示例
讓我們用一個例子來理解這一點。以下是相同的語法。
var promise = new Promise(function(resolve , reject) {
// do a thing, possibly async , then..
if(/*everthing turned out fine */) resolve("stuff worked");
else
reject(Error("It broke"));
});
return promise;
// Give this to someone
實現 Promise 的第一步是建立一個將使用 Promise 的方法。假設在這個例子中,getSum()方法是非同步的,即它的操作不應該阻塞其他方法的執行。一旦此操作完成,它稍後將通知呼叫者。
以下示例(步驟 1)聲明瞭一個 Promise 物件“var promise”。Promise 建構函式將兩個函式作為引數,第一個用於工作成功完成,另一個用於發生錯誤時。
Promise 透過使用 resolve 回撥並傳入結果(即 n1+n2)來返回計算結果。
步驟 1 - resolve(n1 + n2);
如果 getSum() 遇到錯誤或意外情況,它將在 Promise 中呼叫 reject 回撥方法並將錯誤資訊傳遞給呼叫者。
步驟 2 - reject(Error("Negatives not supported"));
方法實現如下面的程式碼所示(步驟 1)。
function getSum(n1, n2) {
varisAnyNegative = function() {
return n1 < 0 || n2 < 0;
}
var promise = new Promise(function(resolve, reject) {
if (isAnyNegative()) {
reject(Error("Negatives not supported"));
}
resolve(n1 + n2)
});
return promise;
}
第二步詳細介紹了呼叫者的實現(步驟 2)。
呼叫者應該使用“then”方法,該方法接受兩個回撥方法——第一個用於成功,第二個用於失敗。每個方法都接受一個引數,如下面的程式碼所示。
getSum(5, 6)
.then(function (result) {
console.log(result);
},
function (error) {
console.log(error);
});
成功執行以上程式碼後,將顯示以下輸出。
11
由於 getSum() 的返回型別是 Promise,因此我們實際上可以有多個“then”語句。第一個 'then' 將有一個返回值。
getSum(5, 6)
.then(function(result) {
console.log(result);
returngetSum(10, 20);
// this returns another promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
},
function(error) {
console.log(error);
});
成功執行以上程式碼後,將顯示以下輸出。
11 30
以下示例使用 getSum() 方法發出三個 then() 呼叫。
<script>
function getSum(n1, n2) {
varisAnyNegative = function() {
return n1 < 0 || n2 < 0;
}
var promise = new Promise(function(resolve, reject) {
if (isAnyNegative()) {
reject(Error("Negatives not supported"));
}
resolve(n1 + n2);
});
return promise;
}
getSum(5, 6)
.then(function(result) {
console.log(result);
returngetSum(10, 20);
//this returns another Promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
returngetSum(30, 40);
//this returns another Promise
},
function(error) {
console.log(error);
})
.then(function(result) {
console.log(result);
},
function(error) {
console.log(error);
});
console.log("End of script ");
</script>
成功執行以上程式碼後,將顯示以下輸出。
程式首先顯示“end of script”,然後依次顯示呼叫 getSum() 方法的結果。
End of script 11 30 70
這表明 getSum() 是以非同步方式或非阻塞方式呼叫的。Promise 提供了一種很好且簡潔的方式來處理回撥函式。