Promise物件概要

lerryteng發表於2018-07-16

Promise是更優雅的實現非同步程式設計的方法(避免了層層巢狀回撥)。

Promise物件有兩種結果狀態:

  1. resolved:表示非同步操作執行成功了
  2. rejected:表示非同步操作執行失敗了

狀態只受非同步操作的影響,與其他無關,並且狀態一旦確定則無法改變。

Promise簡單使用:

const promise = new Promise((resolve, reject) => {
    let condition = false;
    if (condition) {
        resolve('promise ok');
    } else {
        reject(new Error('promise error'));
    }
});
promise.then((val) => {
    console.log('promise resolve', val);
}, (err) => {
    console.log('promise reject', err);
})

// promise reject Error: promise error
複製程式碼
  1. resolve:在非同步操作成功時(resolved狀態)呼叫
  2. reject:在非同步操作失敗時(rejected狀態)呼叫

then方法

  1. 第一個函式引數對應為resolve的執行。
  2. 第二個函式引數對應為rejecte的執行。

其中回撥中如果有return,則返回的是一個新的promise例項,因此可通過鏈式寫法呼叫新promise例項的then方法。如:

promise.then((val) => {
    console.log('promise resolve', val);
    return 'val ok';
}).then((val) => {
    console.log('promise resolve2', val);
})

// promise resolve promise ok
// promise resolve2 val ok
複製程式碼

catch方法

可用於指定發生錯誤時的回撥函式:

  1. 當非同步操作結果變為rejected狀態
  2. then方法指定的回撥函式丟擲錯誤

由於catch可捕獲以上兩種錯誤,因此推薦寫法:

promise.then((val) => {
    console.log('promise resolve', val);
}).catch((err) => {
    console.log('promise reject', err);
})

// promise reject Error: promise error
複製程式碼

如果catch中丟擲一個錯誤,仍可以被後面的catch方法所捕獲。如:

promise.then((val) => {
    console.log('promise resolve', val);
}).catch((err) => {
	console.log('catch1 error', err);
	throw new Error('catch error');
}).catch((err) => {
    console.log('catch2 error:', err);
})

// catch1 error Error: promise error
// catch2 error: Error: catch error

複製程式碼

Promise內如果出現錯誤,但沒有定義錯誤的回撥函式,則不會影響外部的指令碼執行。如:

promise.then((val) => {
    console.log('promise resolve', val);
})
console.log('continue');

// continue
複製程式碼

finally方法

不論promise物件最後狀態如何,都會執行此操作。(回撥函式中不接受引數,其本質是then方法的特例)。如:

const promise = new Promise((resolve, reject) => {
    resolve();
});
promise.then(() => {
    console.log('promise ok');
    throw new Error('then error');
}).catch((err) => {
    console.log('catch', err);
}).finally(() => {
    console.log('finally');
});

// promise ok
// catch Error: then error
// finally
複製程式碼

Promise.all()

接收一個由若干promise物件組成的陣列作為引數。 當所有promise物件的狀態都變成resolved則整體狀態置為resolved,否則整體狀態為rejected。如:

const promise1 = new Promise((resolve, reject) => {
    resolve('promise1 ok');
});
const promise2 = new Promise((resolve, reject) => {
    throw new Error('promise2 error')
});

Promise.all([promise1, promise2]).then(() => {
    console.log('all promises ok');
}).catch((err) => {
    console.log('some promise error', err);
});  

// some promise error Error: promise2 error
複製程式碼

但當promise2定義了catch去捕獲error時,代表promise2的最終狀態會變為resolved,則promise.all執行then方法的回撥。如:

const promise1 = new Promise((resolve, reject) => {
    resolve('promise1 ok');
}).then(() => {
    console.log('promise1 ok');
}).catch((err) => {
    console.log('promise1 err', err);
});
const promise2 = new Promise((resolve, reject) => {
    throw new Error('promise2 error')
}).then(() => {
    console.log('promise2 ok');
}).catch((err) => {
    console.log('promise2 err', err);
});

Promise.all([promise1, promise2]).then(() => {
    console.log('all promises ok');
}).catch((err) => {
    console.log('some promise error', err);
}); 

// promise1 ok
// promise2 err Error: promise2 error
// all promises ok
複製程式碼

Promise.race()

類似於Promise.all(),區別是當第一個promise更新狀態後整體則更新狀態,並且狀態同第一個promise保持一致(與其他promise無關)。如:

const promise1 = new Promise((resolve, reject) => {
    resolve('promise1 ok');
});
const promise2 = new Promise((resolve, reject) => {
    throw new Error('promise2 error');
});

Promise.race([promise1, promise2]).then(() => {
    console.log('first promise ok');
}).catch((err) => {
    console.log('first promise error', err);
});

// first promise ok
複製程式碼

相關文章