Promise 物件
- 含義: Promise是非同步程式設計的一種解決方案,
- 優點: 相比傳統回撥函式和事件更加合理和優雅,Promise是鏈式程式設計(例子),有效的解決了令人頭痛的回撥地獄問題,Promise的結果有成功和失敗兩種狀態,只有非同步操作的結果,可以決定當前是哪一種狀態,外界的任何操作都無法改變這個狀態
- 基本用法:
//ES6 規定,Promise物件是一個建構函式,用來生成Promise例項。 const p = new Promise(function(resolve,reject){
if(success){
resolve('成功的結果')
}else{
reject('失敗的結果')
}
}) p.then(function (res) {
// 接收resolve傳來的資料,做些什麼
},function (err) {
// 接收reject傳來的資料,做些什麼
}) p.catch(function (err) {
// 接收reject傳來的資料或者捕捉到then()中的執行報錯時,做些什麼
}) p.finally(function(){
// 不管什麼狀態都執行
})複製程式碼
- 常用API
- resolve 返回非同步操作成功的結果
- reject 返回非同步操作失敗的結果
- then 執行Promise狀態是成功的操作
- catch 執行Promise狀態是失敗的操作
- finally 不管Promise狀態是成功或失敗都執行的操作
- Promise.all
- Promise.all方法用於將多個 Promise 例項,包裝成一個新的 Promise 例項。
const p = Promise.all([p1, p2, p3])複製程式碼
p的狀態由p1、p2、p3決定,分成兩種情況。(1)只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個陣列,傳遞給p的回撥函式。(2)只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的例項的返回值,會傳遞給p的回撥函式。複製程式碼
Generator 函式
- 含義: Generator 函式是 ES6 提供的一種非同步程式設計解決方案,語法行為與傳統函式完全不同,
-
- 基本用法:
function* helloGenerator() {
yield 'hello';
yield 'Generator';
return 'over';
} let hw = helloGenerator();
hw.next()//{value:"hello",done:false
} hw.next()//{value:"Generator",done:false
} hw.next()//{value:"over",done:true
} hw.next()//{value:undfined,done:true
}複製程式碼
- 特徵:
- 一是,function關鍵字與函式名之間有一個星號;
- 二是,函式體內部使用yield表示式,定義不同的內部狀態;
- 三是,通過next方法獲取每段狀態的返回結果,上面分成4次執行了Gennrator函式,第一次,獲取第一個yield函式的返回結果並暫停,done:false,代表函式內的狀態還沒有執行結束;第二次,同理;第三次,獲取return 的返回結果,done:true表示函式內的狀態已經執行完畢;第四次,函式內已經沒有可以執行的狀態,所有返回undfined,同時告訴函式內的狀態已經執行完畢;如果函式內沒有return,在第三次時返回undfined,done:true表示函式內的狀態已經執行完畢
async 函式
- 含義: async 函式是在ES2017 標準中引入的,async使得非同步操作變得更加方便,其實他就是Generator 函式的語法糖
- 基本用法:
function get1(){
return new Promise((resolve,reject)=>
{
setTimeout(()=>
{resolve(1)
},2000)
})
} async function getSet(){
const n = await get1() //const n = await '111' return n
} getSet().then(console.log)複製程式碼
- 說明:
- await命令只能用在async函式之中,如果用在普通函式,就會報錯。
- await後面是一個Promise物件,如get1 return出去的Promise例項;如果不是 Promise 物件,就直接返回對應的值,如直接返回’111’。
- 1、若Promise 物件, 並且其以值 x 被 fulfilled, 則返回值為 x.
- 2、Promise 物件, 並且其以異常 e 被 rejected, 則丟擲異常 e
- async函式返回的 Promise 物件,必須等到內部所有await命令後面的 Promise 物件執行完,才會發生狀態改變,如果任何一個await語句後面的 Promise 物件變為reject狀態或遇到return,那麼整個async函式都會中斷執行。
- 另外需要注意的是, await 在等待 Promise 物件時會導致 async function 暫停執行, 一直到 Promise 物件決議之後才會 async function 繼續執行.
- 如果我們希望即使前一個非同步操作失敗,也不要中斷後面的非同步操作。這時可以將第一個await放在try…catch結構裡面,這樣不管這個非同步操作是否成功,第二個await都會執行。
async function f() {
try {
await Promise.reject('出錯了');
} catch(e) {
} return await Promise.resolve('hello world');
} f().then(v =>
console.log(v))複製程式碼
- 優點: 相比Generator函式,async函式有如下四點改進
- 內建執行器: Generator 函式的執行必須靠next()進行每一次的模組執行,async自帶執行器,只需要和普通函式一樣呼叫即可執行
- **更好的語義:**async表示函式裡有非同步操作,await表示緊跟在後面的表示式需要等待結果。
- 返回值是Promise: async函式的返回值是 Promise 物件,可以用then方法指定下一步的操作;而且async函式完全可以看做多個非同步函式的操作,包裝成的一個 Promise 物件,而await命令就是內部then命令的語法糖,即Promise.all()的用法
- **更廣的適用性:**相較於Generator函式async函式的await命令後面,可以是 Promise 物件和原始型別的值(數值、字串和布林值,但這時會自動轉成立即 resolved 的 Promise 物件)
- 補充
- 多個await命令後面的非同步操作,如果不存在繼發關係,最好讓它們同時觸發。
//此處省略getFoo(), getBar()兩個函式 // 寫法一 async function getSet(){
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
return [foo, bar]
} // 寫法二 async function getSet(){
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
return [foo, bar]
}複製程式碼
*文章參考ECMAScript 6 入門 *