好家伙,本篇為《JS高級程式設計》第十章“期約與非同步函數”學習筆記 1.非重入期約 1.1.可重入代碼(百度百科) 先來瞭解一個概念 可重入代碼(Reentry code)也叫純代碼(Pure code)是一種允許多個進程同時訪問的代碼。 為了使各進程所執行的代碼完全相同,故不允許任何進程對其進行修 ...
好家伙,本篇為《JS高級程式設計》第十章“期約與非同步函數”學習筆記
1.非重入期約
1.1.可重入代碼(百度百科)
先來瞭解一個概念
可重入代碼(Reentry code)也叫純代碼(Pure code)是一種允許多個進程同時訪問的代碼。
為了使各進程所執行的代碼完全相同,故不允許任何進程對其進行修改。
程式在運行過程中可以被打斷,並由開始處再次執行,並且在合理的範圍內(多次重入,而不造成堆棧溢出等其他問題),
程式可以在被打斷處繼續執行,且執行結果不受影響。
----來自百度百科
1.2.非重入期約
非重入期約方法 期約進入 落定(解決/拒絕)狀態時,與該狀態相關的處理程式不會立即執行 ,
處理程式後的 同步代碼 會在其之前 先執行 ,該特性稱為非重入
當期約進入落定狀態時,與該狀態相關的處理程式僅僅會被排期,而非立即執行。
跟在添加這個處 理程式的代碼之後的同步代碼一定會在處理程式之前先執行。
即使期約一開始就是與附加處理程式關聯 的狀態,執行順序也是這樣的。
這個特性由 JavaScript 運行時保證,被稱為“非重入”(non-reentrancy) 特性。
let promise = new Promise(() => {
console.log("5")
})
// 創建一個期約並將解決函數保存在一個局部變數中
let p = new Promise((resolve) => {
synchronousResolve = function () {
console.log('1');
resolve();
console.log('2');
};
synchronousResolve();
});
p.then(() => console.log('4'));
console.log('3');
看到了嗎,這裡4依舊被放在了最後輸出
這說明在這個例子中,即使期約狀態變化發生在添加處理程式之後,處理程式也會等到運行的消息隊列讓 它出列時才會執行。
2.鄰近處理程式的執行順序
如果給期約添加了多個處理程式,當期約狀態變化時,相關處理程式會按照添加它們的順序依次執行
let p1 = Promise.resolve();
p1.then(() => setTimeout(console.log, 0, 1));
p1.then(() => setTimeout(console.log, 0, 2));
p1.then(() => setTimeout(console.log, 0, 3));
p1.then(() => setTimeout(console.log, 0, 4));
3.期約連鎖
把期約逐個地串聯起來是一種非常有用的編程模式。
之所以可以這樣做,是因為每個期約實例的方 法(then()、catch()和 finally())都會返回一個新的期約對象,
而這個新期約又有自己的實例方,這樣連綴方法調用就可以構成所謂的“期約連鎖”
你應該能想象到,這就是一長串then(),( then()、catch()和 finally()都行 )
let p = new Promise((resolve, reject) => {
resolve();
});
p.then(() => console.log('1'))
.then(() => console.log('2'))
.then(() => console.log('3'))
.then(() => console.log('4'));
4.期約合成
這肯定是個將多個期約合成為一個的某個特性(廢話)
Promise 類提供兩個將多個期約實例組合成一個期約的靜態方法:Promise.all()和 Promise.race()。
而合成後期約的行為取決於內部期約的行為。
4.1.Promise.all()
特性一:合成的期約只會在每個包含的期約都解決之後才解決
特性二:如果至少有一個包含的期約待定,則合成的期約也會待定。
如果有一個包含的期約拒絕,則合成的 期約也會拒絕
let p1 = Promise.all([
Promise.resolve(),
new Promise((resolve, reject) => {
resolve();
})
]);
console.log("I'm p1");
console.log(p1);
// 一次拒絕會導致最終期約拒絕
let p2 = Promise.all([
Promise.resolve(),
Promise.reject(),
Promise.resolve()
]);
console.log("I'm p2");
console.log(p2);
let p3 = Promise.all([
Promise.resolve(),
new Promise(() => {}),
Promise.resolve()
]);
console.log("I'm p3");
console.log(p3);
4.2.Promise.race()
Promise.race()不會對解決或拒絕的期約區別對待。
無論是解決還是拒絕,只要是第一個落定的 期約,Promise.race()就會包裝其解決值或拒絕理由並返回新期約
let p1 = Promise.race([
Promise.resolve(),
new Promise((resolve, reject) => {
resolve();
})
]);
console.log("I'm p1");
console.log(p1);
// 一次拒絕會導致最終期約拒絕
let p2 = Promise.race([
Promise.resolve(),
Promise.reject(),
Promise.resolve()
]);
console.log("I'm p2");
console.log(p2);
let p3 = Promise.race([
Promise.resolve(),
new Promise(() => {}),
Promise.resolve()
]);
console.log("I'm p3");
console.log(p3);
5.課後練習
1.什麼是promise期約連鎖?
答:Promise期約連鎖調用是使用Promise的一種技術,它可以讓你把多個Promise以鏈式的方式組合起來,每個Promise的結果作為下一個Promise的輸入。
這樣可以把複雜的操作分解成一系列簡單的操作,以便更容易理解和管理。
2.如何解釋Promise的的非重入特性?
答:非重入期約方法 期約進入 落定(解決/拒絕)狀態時,與該狀態相關的處理程式不會立即執行 ,
處理程式後的 同步代碼 會在其之前 先執行 ,該特性稱為非重入