MDN Promise 文檔javascript
Promise 及其做用java
Promise 的 executor 函數和狀態ajax
Promise 狀態編程
Promise 中的 then 和 catch設計模式
Promise 中其它經常使用方法數組
Promise 的誕生就是爲了解決異步請求中的回調地獄問題:它是一種設計模式,ES6 中提供了一個 JS 內置類 Promise,來實現這種設計模式promise
function ajax1() { return new Promise((resolve) => { $.ajax({ url: "/url1", // ... success: resolve, }); }); } function ajax2() { return new Promise((resolve) => { $.ajax({ url: "/url2", // ... success: resolve, }); }); } function ajax3() { return new Promise((resolve) => { $.ajax({ url: "/url3", // ... success: resolve, }); }); } ajax1() .then((result) => { return ajax2(result.map((item) => item.id)); }) .then((result) => { return ajax3(); }) .then((result) => {});
回調地獄:上一個回調函數中繼續作事情,並且繼續回調(在真實項目的 AJAX 請求中常常出現回調地獄)=> 異步請求、不方便代碼的維護dom
new Promise([executor]) ,[executor]執行函數是必須傳遞的異步
Promise 是用來管理異步編程的,它自己不是異步的。async
new Promise 的時候會當即把 executor 函數執行(只不過咱們通常會在 executor 函數中處理一個異步操做)
// new Promise 的時候會當即把 executor 函數執行 let p1 = new Promise(() => { setTimeout((_) => { console.log(1); }, 1000); console.log(2); }); console.log(3); // 2.3.1
Promise {<pending>} __propt__:Promise [[PromiseStatus]]:"pending" [[PromiseValue]]:"undefined" // Promise 自己有一個 Value 值,用來記錄成功的結果(或者是失敗的緣由的) =>[[PromiseValue]]
Promise 自己有三個狀態 => [[PromiseStatus]]
let p1 = new Promise((resolve, reject) => { setTimeout((_) => { // 通常會在異步操做結束後,執行resolve/reject函數,執行這兩個函數中的一個,均可以修改Promise的[[PromiseStatus]]/[[PromiseValue]] // 一旦狀態被改變,在執行resolve、reject就沒有用了 resolve("ok"); reject("no"); }, 1000); });
new Promise 的時候先執行 executor 函數,在這裏開啓了一個異步操做的任務(此時不等:把其放入到 EventQuque 任務隊列中),繼續執行
p1.then 基於 then 方法,存儲起來兩個函數(此時這兩個函數尚未執行);當 executor 函數中的異步操做結束了,基於 resolve/reject 控制 Promise 狀態,從而決定執行 then 存儲的函數中的某一個
let p1 = new Promise((resolve, reject) => { setTimeout((_) => { let ran = Math.random(); console.log(ran); if (ran < 0.5) { reject("NO!"); return; } resolve("OK!"); }, 1000); }); // then:設置成功或者失敗後處理的方法 // Promise.prototype.then([resolvedFn],[rejectedFn]) p1.then( // 成功函數 (result) => { console.log(`成功:` + result); }, // 失敗函數 (reason) => { console.log(`失敗:` + reason); } );
resolve/reject 的執行,不管是否放到一個異步操做中,都須要等待 then 先執行完,把方法存儲好,纔會在更改狀態後執行 then 中對應的方法 => 此處是一個異步操做(因此不少人說 Promise 是異步的),並且是微任務操做
let p1 = new Promise((resolve, reject) => { resolve(100); }); p1.then( (result) => { console.log(`成功:` + result); }, (reason) => { console.log(`失敗:` + reason); } ); console.log(3); // 3 // 成功:100
建立一個狀態爲成功/失敗的 PROMISE 實例
這樣的寫法也能夠被這種寫法代替
Promise.resolve(100) | Promise.reject(0)
then 中也能夠只寫一個或者不寫函數 ( .then(fn) | .then(null,fn) )
Promise.prototype.catch(fn)
===> .then(null,fn)
Promise.resolve(10) .then((result) => { console(a); //=>報錯了 }) .catch((reason) => { console.log(`失敗:${reason}`); });
then 方法結束都會返回一個新的 Promise 實例(then 鏈)
p1 這個 new Promise 出來的實例,成功或者失敗,取決於 executor 函數執行的時候,執行的是 resolve 仍是 reject 決定的,再或者 executor 函數執行發生異常錯誤,也是會把實例狀態改成失敗的
p2/p3 這種每一次執行 then 返回的新實例的狀態,由 then 中存儲的方法執行的結果來決定最後的狀態(上一個 THEN 中某個方法執行的結果,決定下一個 then 中哪個方法會被執行)
=> 不管是成功的方法執行,仍是失敗的方法執行(then 中的兩個方法),凡是執行拋出了異常,則都會把實例的狀態改成失敗
=> 方法中若是返回一個新的 Promise 實例,返回這個實例的結果是成功仍是失敗,也決定了當前實例是成功仍是失敗
=> 剩下的狀況基本上都是讓實例變爲成功的狀態 (方法返回的結果是當前實例的 value 值:上一個 then 中方法返回的結果會傳遞到下一個 then 的方法中)
let p1 = new Promise((resolve, reject) => { resolve(100); }); let p2 = p1.then( (result) => { console.log("成功:" + result); return result + 100; }, (reason) => { console.log("失敗:" + reason); return reason - 100; } ); let p3 = p2.then( (result) => { console.log("成功:" + result); }, (reason) => { console.log("失敗:" + reason); } );
then 鏈式調用:
Promise.resolve(10) .then( (result) => { console.log(`成功:${result}`); return Promise.reject(result * 10); }, (reason) => { console.log(`失敗:${reason}`); } ) .then( (result) => { console.log(`成功:${result}`); }, (reason) => { console.log(`失敗:${reason}`); } );
遇到一個 then,要執行成功或者失敗的方法,若是此方法並無在當前 then 中被定義,則順延到下一個對應的函數
Promise.reject(10) .then((result) => { console.log(`成功:${result}`); return result * 10; }) .then(null, (reason) => { console.log(`失敗:${reason}`); }); // 失敗:10
Promise.all(arr):返回的結果是一個 Promise 實例(all 實例),要求 arr 數組中的每一項都是一個新的 Promise 實例,Promise.all 是等待全部數組中的實例狀態都爲成功纔會讓「all 實例」狀態爲成功,Value 是一個集合,存儲着 arr 中每個實例返回的結果;凡是 arr 中有一個實例狀態爲失敗,「all 實例」的狀態也是失敗
let p1 = Promise.resolve(1); let p2 = new Promise((resolve) => { setTimeout((_) => { resolve(2); }, 1000); }); let p3 = Promise.reject(3); Promise.all([p2, p1]) .then((result) => { // 返回的結果是按照 arr 中編寫實例的順序組合在一塊兒的 // [2,1] console.log(`成功:${result}`); }) .catch((reason) => { console.log(`失敗:${reason}`); });
Promise.race(arr):和 all 不一樣的地方,race 是賽跑,也就是 arr 中無論哪個先處理完,處理完的結果做爲「race 實例」的結果
let p1 = Promise.resolve(100); let p2 = new Promise((resolve) => { setTimeout((_) => { resolve(200); }, 1000); }); let p3 = Promise.reject(3); // 1 2 100
ES7 中提供了 Promise 操做的語法糖:async / await
async function handle() { let result = await ajax1(); result = await ajax2(result.map((item) => item.id)); result = await ajax3(); // 此處的result就是三次異步請求後獲取的信息 } handle();
async 是讓一個普通函數返回的結果變爲 status=resolved 而且 value=return 結構的 Promise 實例
async 最主要的做用是配合 await 使用的,由於一旦在函數中使用 await,那麼當前的函數必須用 async 修飾
await 會等待當前 Promise 的返回結果,只有返回的狀態是 resolved 狀況,纔會把返回結果賦值給 result
await 不是同步編程,是異步編程(微任務):當代碼執行到此行(先把此行),構建一個異步的微任務(等待 Promise 返回結果,而且 Promise 下面的代碼也都被列到任務隊列中),
const p1 = () => new Promise(); const p2 = () => new Promise(); async function fn() { console.log(1); let result = await p2; console.log(result); let AA = await p1; console.log(AA); } fn(); console.log(2); // 2 // 1 // p2 result // p1 AA
若是 Promise 是失敗狀態,則 await 不會接收其返回結果,await 下面的代碼也不會在繼續執行( await 只能處理 Promise 爲成功狀態的時候)
const p3 = Promise.reject(10); async function fn() { let reason = await p3; console.log(reason); } fn(); //
編輯時間:2020-08-18 21:15