Promise
Promise 介紹
Promise 物件表示一個異步操作的最終完成(或失敗)及其結果值,
狀態:
一個 promise 必然處于以下幾種狀態之一
- 待定:初始狀態(pending)
- 已兌現:操作成功完成(fulfilled)
- 已拒絕:操作失敗(reject)
創建 Promise
Promise 物件是由關鍵字 new 及其建構式來創建的,該建構式會把一個叫做“處理器函式”(executor function)的函式作為它的引數,這個“處理器函式”接受兩個函式——resolve 和 reject ——作為其引數,當異步任務順利完成且回傳結果值時,會呼叫 resolve 函式;而當異步任務失敗且回傳失敗原因(通常是一個錯誤物件)時,會呼叫 reject 函式,
new Promise((resolve, reject) => {
//處理操作 回傳resolve或者reject
if (flag) resolve(data);
eles(reject(data));
});
需要某個自定義的函式,變成 Promise 只需回傳一個 Promise 即可
function myFun(flag) {
return new Promise((resolve, reject) => {
//處理操作 回傳resolve或者reject
if (flag) resolve(data);
eles(reject(errorData));
});
}
在具體專案中,使用 Promise 封裝獲取當前配置方法,
/**
* 獲取字典串列
* axios : axios
* lang : 當前傳入語言 ,根據不同語言,獲取配置不同
*
* 判斷sessionStorage里是否獲取到當前所需要字典配置,
* 如果有回傳該配置,獲取不到再從介面中獲取資料,并保存到sessionStorage,
*/
function getDictionary(axios, lang) {
// 查看sessionStorage
const dic = sessionStorage.getItem("dictionary_data_" + lang) || null;
// 回傳一個Promise物件
return new Promise((resolve, reject) => {
if (dic) resolve(JSON.parse(dic));
else {
axios
.get(`/api/dictionary?language=${lang}`)
.then((res) => {
const dic_data = https://www.cnblogs.com/yevin/p/{};
if (res.data.code === 0 && res.data.result) {
res.data.result.forEach((r) => (dic_data[r.itemName] = r));
//存放sessionStorage
sessionStorage.setItem("dictionary_data_" + lang,
JSON.stringify(dic_data)
);
// 回傳資料
resolve(dic_data);
} else reject();
})
.catch((error) => reject());
}
});
}
靜態方法
Primise.all(iterable)
傳參需要是一個可迭代物件
Promise.all 回傳一個 Promise 物件,
該 Promise 物件會在 Promise.all 的 iterable 引數物件里的所有 Promise 物件都成功才會觸發,
簡單來說就是只有 Promise.all 引數里的所有 Promise 成功才會觸發,有一個失敗就不會觸發,
例如:
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3]);
}, 2000);
});
Promise.all([promise1, promise2, promise3]).then((res) => {
console.log(res);
});
上面代碼 會在大約兩秒之后 列印輸出 [ 'heihei', 'wenbo', [ 1, 2, 3 ] ]
因為 Promise.all 需要等待 promise3 中的 setTimeout 完成后才會觸發回傳 Promise 物件
又例如:
var promise1 = Promise.reject("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3]);
}, 2000);
});
Promise.all([promise1, promise2, promise3])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
上面代碼,并不會在等待 2 秒左右輸出[ 'heihei', 'wenbo', [ 1, 2, 3 ] ],而會直接輸出heihei因為在 promise1 中回傳的是一個 reject,Promise.all認為promise1失敗(rejected),Promise.all會異步的將失敗的結果回傳,而不管其它 promise 是否完成,
在某些特定的場合,需要 Promise.all 回傳的資料,才讓繼續執行代碼,因為Promise.all是異步的,我們可以借助 async 與 await 實作,
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3]);
}, 2000);
});
function demo() {
Promise.all([promise1, promise2, promise3]).then((res) => {
console.log(res);
});
console.log("heihei");
}
demo();
以上代碼會在執行之后 先列印"heihei",之后 2 秒左右才會列印輸出[ 'heihei', 'wenbo', [ 1, 2, 3 ] ]
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3]);
}, 2000);
});
async function demo() {
await Promise.all([promise1, promise2, promise3]).then((res) => {
console.log(res);
});
console.log("heihei");
}
demo();
上方在使用了 async 和 await之后 會等在 Promise.all 執行完成之后才會列印輸出heihei,在實際專案中可以在下面使用Promise.all回傳的資料進行操作,
Promise.allSettled(iterable)
傳參需要是一個可迭代物件
Promise.allSettled 回傳一個 Promise 物件,
該 Promise 物件會在 Promise.allSettled 的 iterable 引數物件里的所有 Promise 物件都成功或者失敗才會觸發,
簡單說就是等所有的 Promise 執行完成才會觸發,無論成功還是失敗,
var promise1 = Promise.reject("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3]);
}, 2000);
});
Promise.allSettled([promise1, promise2, promise3])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
輸出為:
[
{ status: "rejected", reason: "heihei" },
{ status: "fulfilled", value: "wenbo" },
{ status: "fulfilled", value: [1, 2, 3] },
];
可以看到Promise.allSettled的回傳值為一個陣列,陣列里包括每個 Promise 的狀態status,回傳值value,和 rejected 的值reason
和Promise.all() 相比,Promise.all() 更適合彼此相互依賴或者在其中任何一個 reject 時立即結束,
Promise.any(iterable)
傳參需要是一個可迭代物件
Promise.any 回傳一個 Promise 物件,
接收一個 Promise 物件的集合,當其中的一個 promise 成功,就回傳那個成功的 promise 的值,
var promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([4000]);
}, 4000);
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1000]);
}, 1000);
});
Promise.any([promise1, promise2])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
簡單來說, Promise.any 像是競速模式,那個 Promise 先成功,就回傳哪一個 Promise
Promise.any 和 Promise.all 是相反的,一個是全部成功才觸發,一個只要有一個成功就觸發,
var promise1 = Promise.reject("error");
var promise2 = Promise.reject("error2");
Promise.any([promise1, promise2])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
//輸出
//AggregateError: All promises were rejected
如上代碼,當所有 Promise 都沒有成功時,將回傳一個 Error 的 Promise
Promise.race(iterable)
傳參需要是一個可迭代物件
Promise.any 回傳一個 Promise 物件,
接收一個 Promise 物件的集合,當其中的一個 promise 成功或者失敗時,就回傳那個成功或者失敗的 promise 的值,
和 Promise.any 對比,Promise.any 為當有一個成功時,回傳成功的 promise,Promise.race 則是不論成功失敗都回傳
var promise1 = Promise.resolve("resolve");
var promise2 = Promise.reject("error");
Promise.race([promise1, promise2])
.then((res) => {
console.log(res); //resolve
})
.catch((e) => {
console.log(e);
});
// 輸出為resolve
var promise1 = Promise.reject("error");
var promise2 = Promise.resolve("resolve");
Promise.race([promise1, promise2])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e); //error
});
//輸出為 error
Promise.reject(reason)
回傳一個狀態為失敗的 Promise 物件,并將給定的失敗資訊傳遞給對應的處理方法
Promise.reject()方法回傳一個帶有拒絕原因的 Promise 物件,
Promise.reject("test-reject")
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e); //test-reject
});
Promise.resolve(value)
回傳一個狀態由給定 value 決定的 Promise 物件
如果這個是一個 Promise 物件,則回傳這 Promise 物件,
如果這個值是 thenable(即帶有"then" 方法),回傳的 promise 會“跟隨”這個 thenable 的物件,采用它的最終狀態
Promise.resolve("test-resolve")
.then((res) => {
console.log(res); //test-resolve
})
.catch((e) => {
console.log(e);
});
當 Resolve 是一個 Promise 物件,則回傳這個 Promise 物件,
var promise = Promise.resolve({
name: "resolve",
});
Promise.resolve(promise)
.then((res) => {
console.log(res); //{name:resolve}
})
.catch((e) => {
console.log(e);
});
//reject情況
var promise = Promise.reject({
name: "reject",
});
Promise.resolve(promise)
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e); //{name:reject}
});
當 Resolve 是一個 thenable 物件時
var p1 = Promise.resolve({
then: function (resolve, reject) {
resolve("hello ~!");
},
});
p1.then((res) => {
console.log(res); //hello ~!
});
注意:要在決議為自身的 thenable 上呼叫 Promise.resolve,這將導致無限遞回,
Promise 原型方法
Promise.prototype.catch(onRejected)
catch() 方法回傳一個 Promise ,并且處理拒絕的情況
實際上 catch 的行為與呼叫 Promise.prototype.then(undefined, onRejected) 相同
obj.catch(onRejected) 內部 calls obj.then(undefined, onRejected)
var promise = new Promise((resolve, reject) => {
throw "出現了錯誤~";
});
promise.then(
(res) => {
console.log(res);
},
(e) => {
console.log(e); //出現了錯誤~
}
);
promise
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e); //出現了錯誤~
});
以上兩種方法 都可以實作例外的捕獲
Promise.prototype.then(onFulfilled, onRejected)
then() 方法回傳一個 Promise,它最多需要有兩個引數:Promise 的成功和失敗情況的回呼函式,
當只穿一個值得時候默認是 Promise 成功的回呼函式
//默認一個引數
var promise = new Promise((resolve, reject) => {
resolve("成功~");
//or
// reject('失敗~')
});
promise.then(
(res) => {
console.log(res); //成功~
},
(error) => {
console.log(error); // 失敗~
}
);
Promise.prototype.finally(onFinally)
finally() 方法回傳一個 Promise,在 promise 結束時,無論結果是 fulfilled 或者是 rejected,都會執行指定的回呼函式,這為在 Promise 是否成功完成后都需要執行的代碼提供了一種方式,
這避免了同樣的陳述句需要在 then()和 catch()中各寫一次的情況,
var promise = new Promise((resolve, reject) => {
resolve("成功~");
//or
// reject('失敗~')
});
promise
.then(
(res) => {
console.log(res); //成功~
},
(error) => {
console.log(error); // 失敗~
}
)
.finally((res) => {
console.log("finally~");
});
如以上代碼所示,無論 Promise 回傳 resolve 還是 reject,都會執行 finally 里的內容,
鏈式使用
由于 promise.then(),promise.catch() 和 promise.finally()可以對已完成(成功或者失敗)的 Promise 進行操作,還會回傳一個新的 Promise 物件,在新的 Promise 物件上我們還可以使用這些方法進行操作,形成一個鏈式操作,
var promise = new Promise((resolve, reject) => {
resolve("成功~");
});
promise
.then((res) => {
console.log(res); //成功
return new Promise((resolve, reject) => {
resolve("成功01~");
});
})
.then((res) => {
console.log(res); //成功01~
return new Promise((resolve, reject) => {
resolve("成功02~");
});
})
.then((res) => {
console.log(res); //成功02~
throw "error~";
})
.catch((e) => {
console.log(e); //error~
});
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/276596.html
標籤:JavaScript
