前端JavaScript經(jīng)典之Promise詳解
1. Promise 由來
在以前我們實現(xiàn)異步是用的回調函數(shù),當一個異步請求需要依賴上一個異步請求返回的結果的時候,就會形成如下這種的調用結構。
請求1(function (結果1) { 請求2(function (結果2) { 請求3(function(結果3)) { 請求4(function(結果4) {}) } }); });
這種結構看著很雜亂且不易維護,被我們親切的叫做 “回調地獄”。為了解決回調地獄的問題,Promise 就誕生了。
Promise 誕生的使命:優(yōu)雅的去表示異步回調。
2. Promise 基礎概念
2.1 創(chuàng)建 promise 實例
Promise 是一個構造函數(shù),所以我們在調用一個 Promsie 的時候,要用 new Promsie 的方式去調用。
const ps = new Promise();
new Promise 接受一個函數(shù)類型的參數(shù)。這個函數(shù)又接收兩個參數(shù) resolve 和 reject,分別對映成功回調和失敗回調。Promise 內部有 3 種狀態(tài) pending(進行時),fulfilled(已成功),rejected(已失?。?/strong>。且這三種狀態(tài)是不可逆的,只能由 pending 到 fulfilled,pending 到 rejected。resolve 使 promise 狀態(tài)由 pending 到 fulfilled,reject 使 promise 狀態(tài)由 pending 到 rejected。
const ps = new Promise(function () {});
const ps = new Promise(function (resolve, reject) { let number = 10; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } });
2.2 實例方法
為了更好的控制下一步執(zhí)行,又誕生了三個實例方法 then、catch、finally。
2.2.1 then 方法
then 方法一般接受兩個參數(shù) resolve、reject。分別對應成功時的回調和失敗時的回調。
成功狀態(tài)的 promise 實例
const ps1 = new Promise(function (resolve, reject) { let number = 10; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } }); ps1.then(function (res) { console.log(res); });
失敗狀態(tài)的 promise 實例
const ps2 = new Promise(function (resolve, reject) { let number = 9; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } }); ps2.then( function (res) {}, function (err) { console.log(err); } );
2.2.2 catch 方法
then 方法支持鏈式調用,then 的執(zhí)行嚴重依賴上一步的結果,上一步如果沒有結果,那么下一步就不會執(zhí)行。但是每一步都寫 reject 特別麻煩,所以誕生了 catch,then 就可以省略 reject 方法,reject 方法就交給 catch 執(zhí)行,同時 catch 還可以捕獲執(zhí)行 resolve 的異常。
const ps2 = new Promise(function (resolve, reject) { let number = 9; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } }); ps2 .then(function (res) {}) .catch(function (err) { console.log(err); });
2.2.3 finally 方法
有的時候,無論成功還是失敗都需要執(zhí)行一些操作,就誕生了 finally。我們可以在這做一些清理工作。
const ps2 = new Promise(function (resolve, reject) { let number = 9; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } }); ps2 .then(function (res) {}) .catch(function (err) { console.log(err); }) .finally(function () { console.log("end"); });
2.2.4 then 的鏈式調用
因為 then 方法支持鏈式調用,所以我們需要知道使用 then 方法會有什么效果。只要調用 promise 實例的 then 方法一定產(chǎn)生一個新的 promise,這個 promise 的狀態(tài)由里面的函數(shù)決定。函數(shù)什么時候有結果,這個新 promise 狀態(tài)什么時候由 pending 轉 fulfilled。catch 和 finally 同理。
const ps = new Promise(function (resolve, reject) { let number = 10; if (number >= 10) { resolve(number); } else { reject("number 小于10"); } }); ps.then(function (res) { return res * 10; }) .then(function (res) { return res + 2; }) .then(function (res) { if (res > 100) { console.log(res); } else { console.log("最后結果小于100"); } });
3. Promise 原型方法
為了滿足更多的業(yè)務需要,又誕生了 6 個原型方法 Promise.all()、Promise.allSettled()、Promise.any()、Promise.race()、Promise.reject()、Promise.resolve()。且都會返回一個確定狀態(tài)的 Promsie 對象。
統(tǒng)一使用兩個成功異步 ps1、ps2。兩個失敗異步 ps3、ps4。作為測試用例。如下:
const ps1 = new Promise(function (resolve, reject) { setTimeout(() => { resolve("成功結果1"); }, 1000); }); const ps2 = new Promise(function (resolve, reject) { setTimeout(() => { resolve("成功結果2"); }, 2000); }); const ps3 = new Promise(function (resolve, reject) { setTimeout(() => { reject("失敗結果1"); }, 3000); }); const ps4 = new Promise(function (resolve, reject) { setTimeout(() => { reject("失敗結果2"); }, 2000); });
3.1 Promise.all()
通過數(shù)組的形式傳入異步操作,所有的異步執(zhí)行都成功,才執(zhí)行成功,如果有一個失敗了,就執(zhí)行失敗。例子如下:
都成功,執(zhí)行 then 方法,成功返回結果,通過 res 以數(shù)組的方式返回
Promise.all([ps1, ps2]) .then(function (res) { console.log("都成功", res); }) .catch(function (err) { console.log(err); });
按傳入順序執(zhí)行,如果有一個異步執(zhí)行失敗,中斷其他異步操作,執(zhí)行 catch 方法,通過 err 返回失敗結果
Promise.all([ps1, ps2, ps3, ps4]) .then(function (res) { console.log("都成功", res); }) .catch(function (err) { console.log("執(zhí)行失敗", err); });
3.2 Promise.allSettled()
所有執(zhí)行都有結果了就執(zhí)行,無論成功還是失敗
Promise.allSettled([ps1, ps2, ps3, ps4]).then(function (res) { console.log("都返回結果", res); });
3.3 Promise.any()
任意異步成功了就執(zhí)行
Promise.any([ps1, ps2, ps3, ps4]).then(function (res) { console.log("任意成功", res); });
3.4 Promise.race()
任意異步成功或失敗就執(zhí)行。
Promise.race([ps1, ps2, ps3, ps4]).then(function (res) { console.log("任意成功或失敗", res); });
3.5 Promise.reject()
返回一個狀態(tài)為 rejected 的 Promise 對象
3.6 Promise.resolve()
會接收 4 種類型的參數(shù):promise 實例 、具有 then 方法的對象、沒有 then 方法的對象、不傳參
當參數(shù)是一個 Promise 實例時,直接返回這個實例。
Promise.resolve(ps1);
當參數(shù)是一個具有 then 方法的對象時,將這個對象轉為 Promise 對象,并立即執(zhí)行對象的 then 方法
let obj = { name: "yqcoder", then(resolve) { resolve(this.name); }, }; Promise.resolve(obj);
當參數(shù)是一個沒有 then 方法的對象,或者參數(shù)不是對象時,就會返回狀態(tài)為 fulfilled 的新的 Promise 對象,并將參數(shù)傳入下一個 then。
let obj = { name: "yqcoder", }; let ps = Promise.resolve(obj); ps.then(function (res) { console.log("結果", res); });
當不帶任何參數(shù)時,就會返回一個狀態(tài)為 fulfilled 的 Promise 對象
Promise.resolve();
總結
到此這篇關于前端JavaScript經(jīng)典之Promise的文章就介紹到這了,更多相關前端JS Promise詳解內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
9行javascript代碼獲取QQ群成員具體實現(xiàn)
22 行 JavaScript 代碼實現(xiàn) QQ 群成員提取器,如果沒有達到效果可能原因一是QQ版本升級了,二是博客里面的代碼也有些繁瑣2013-10-10JS 實現(xiàn)BASE64_ENCODE和BASE64_DECODE(實例代碼)
JS 實現(xiàn)BASE64_ENCODE和BASE64_DECODE(實例代碼)。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11js報錯:Maximum?call?stack?size?exceeded的解決方法
這篇文章主要給大家介紹了關于js報錯Maximum?call?stack?size?exceeded的解決方法,文中通過實例代碼將解決的方法介紹的非常詳細,需要的朋友可以參考下2023-02-02JavaScript中停止執(zhí)行setInterval和setTimeout事件的方法
這篇文章主要介紹了JavaScript中停止執(zhí)行setInterval和setTimeout事件的方法,本文給出操作實例代碼和語法介紹,需要的朋友可以參考下2015-05-05