一、 Promise.resolve()
有時需要將現有對象轉為 Promise 對象,Promise.resolve方法就起到這個作用。
const jsPromise = Promise.resolve($.ajax('/whatever.json'));
Promise.resolve等價於下面的寫法。
Promise.resolve('foo') // 等價於 new Promise(resolve => resolve('foo'))
Promise.resolve方法的參數分成四種情況。
(1)參數是一個 Promise 實例
如果參數是 Promise 實例,那么Promise.resolve將不做任何修改、原封不動地返回這個實例。
//如果傳入的 value 本身就是 Promise 對象,則該對象作為 Promise.resolve 方法的返回值返回。 function fn(resolve) { setTimeout(function () { return resolve(123); }, 3000); } let p0 = new Promise(fn); let p1 = Promise.resolve(p0); // 返回為true,返回的 Promise 即是 入參的 Promise 對象。 console.log(p0 === p1);
(2)參數是一個thenable對象
thenable對象指的是具有then方法的對象,比如下面這個對象。
let thenable = { then: function(resolve, reject) { resolve(42); } };
Promise.resolve方法會將這個對象轉為 Promise 對象,然后就立即執行thenable對象的then方法。
ES6 Promises 里提到了 Thenable 這個概念,簡單來說它就是一個非常類似 Promise 的東西。最簡單的例子就是 jQuery.ajax,它的返回值就是 thenable 對象。
但是要謹記,並不是只要實現了 then 方法就一定能作為 Promise 對象來使用。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代碼中,thenable對象的then方法執行后,對象p1的狀態就變為resolved,從而立即執行最后那個then方法指定的回調函數,輸出 42。 ###(3)參數不是具有then方法的對象,或根本就不是對象 如果參數是一個原始值,或者是一個不具有then方法的對象,則Promise.resolve方法返回一個新的 Promise 對象,狀態為resolved。 ```JS const p = Promise.resolve('Hello'); p.then(function (s){ console.log(s) }); // Hello
上面代碼生成一個新的 Promise 對象的實例p。由於字符串Hello不屬於異步操作(判斷方法是字符串對象不具有 then 方法),返回 Promise 實例的狀態從一生成就是resolved,所以回調函數會立即執行。
Promise.resolve方法的參數,會同時傳給回調函數。
(4) 不帶有任何參數
Promise.resolve方法允許調用時不帶參數,直接返回一個resolved狀態的 Promise 對象。
所以,如果希望得到一個 Promise 對象,比較方便的方法就是直接調用Promise.resolve方法。
const p = Promise.resolve(); p.then(function () { // ... });
上面代碼的變量p就是一個 Promise 對象。
參數不是具有then方法的對象,或根本就不是對象
如果參數是一個原始值,或者是一個不具有then方法的對象,則Promise.resolve方法返回一個新的 Promise 對象,狀態為resolved。
const p = Promise.resolve('Hello'); p.then(function (s){ console.log(s) }); // Hello
需要注意的是,立即resolve的 Promise 對象,是在本輪“事件循環”(event loop)的結束時,而不是在下一輪“事件循環”的開始時
setTimeout(function () { console.log('three'); }, 0); Promise.resolve().then(function () { console.log('two'); }); console.log('one'); // one // two // three
上面代碼中,setTimeout(fn, 0)在下一輪“事件循環”開始時執行,Promise.resolve()在本輪“事件循環”結束時執行,console.log('one')則是立即執行,因此最先輸出。
Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); console.log(1); // 1, 2, 3
需要注意的是,立即resolve的 Promise 對象,是在本輪“事件循環”(event loop)的結束時執行執行,不是馬上執行,也不是在下一輪“事件循環”的開始時執行
原因:傳遞到 then()
中的函數被置入了一個微任務隊列,而不是立即執行,這意味着它是在 JavaScript 事件隊列的所有運行時結束了,事件隊列被清空之后,才開始執行
二、 Promise.reject()
類方法,且與 resolve 唯一的不同是,返回的 promise 對象的狀態為 rejected。
Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態為rejected。
const p = Promise.reject('出錯了'); // 等同於 const p = new Promise((resolve, reject) => reject('出錯了')) p.then(null, function (s) { console.log(s) }); // 出錯了
上面代碼生成一個 Promise 對象的實例p,狀態為rejected,回調函數會立即執行。
注意,Promise.reject()方法的參數,會原封不動地作為reject的理由,變成后續方法的參數。這一點與Promise.resolve方法不一致
const thenable = { then(resolve, reject) { reject('出錯了'); } }; Promise.reject(thenable) .catch(e => { console.log(e === thenable) }) // true
原文鏈接:https://www.jianshu.com/p/b511bfc58ae9