promise 學習筆記

promise 是什么

Promise 對象用于一個異步操作的最終完成(或失敗)及其結果值的表示。(簡單說就是處理異步請求。一個諾言,一個成功,一個失敗。)

看個例子

var promise = new Promise(function(resolve){
    resolve(42);
});
promise.then(function(value){
    console.log(value);
}).catch(function(error){
    console.error(error);
});

運行后,打印出42,為什么會是42呢?帶著這個疑惑繼續放下看

promise 狀態

一個Promise必須處在其中之一的狀態:pending, fulfilled 或 rejected.

pending 狀態:可以轉換到 fulfilled 或 rejected 狀態。
fulfilled 狀態:不能轉換成任何其它狀態;必須有一個值,且這個值不能被改變。
rejected 狀態:不能轉換成任何其它狀態;必須有一個值,且這個值不能被改變。

promise 對象

創建 promise 對象

1.new Promise(fn) 返回一個 promise 對象。

2.fn是個函數,fn有兩個參數

  • resolve:處理結果成功的時候調用resolve(處理結果值)
  • reject:處理結果錯誤的時候調用reject(Error對象)

then 方法

一個 Promise 必須提供一個 then 方法來獲取其值。

Promise 的 then 方法接受兩個參數:

promise.then(onFulfilled,onRejected)

1.onFulfilled 和 onRejected 都是函數,如果不是函數,則忽略之。
2.onFulfilled :resolve(成功)時調用 onFulfilled,必須在promise fulfilled后調用,且promise的value為其第一個參數,不能多次調用。
3.onRejected:reject(失敗)時調用 onRejected,必須在promise rejected后調用, 且promise的reason為其第一個參數,不能被多次調用。

.catch只是 promise.then(undefined, onRejected) 的別名而已。

Promise.reject(new Error("BOOM!")).catch(function(error){
    console.error(error);  // Error: BOOM!
});

開始那個例子就變成簡單明了,relove(42) 成功是調用function(value){console.log(value)},所以打印出 42 。

對于一個 promise,它的 then 方法可以調用多次。

promise.then(onFulfilled,onRejected).then(onFulfilled,onRejected);
promise.then(onFulfilled,onRejected); promise.then(onFulfilled,onRejected);

then 必須返回一個 promise

promise2 = promise1.then(onFulfilled, onRejected);

創建 XHR 的promise 對象

function ajax(options){
  return new Promise(function(resolve,reject){
    let {method,url} = options;
    let xhr = new XMLHttpRequest();
    xhr.open(method,url);
    xhr.onload = function(){
      if(xhr.status === 200){
        resolve(xhr.responseText)
      }else{
        reject(new Error(xhr.statusText))
      }
    };
    xhr.onerror = function(){
      reject(new Error(xhr.statusText))
    };
    xhr.send()
  })
}
// 運行
var promise = ajax({method:'GET',url:'xxx.json'});
promise.then(function(value){
  console.log(value)
},function(reason){
  console.error(reason)
})
// xxx.json
{
  "name":"jack",
  "nationality":"china"
}

ajax 只有在通過XHR取得結果狀態為200時才會調用 resolve 。而其他情況(取得失敗)時則會調用 reject 方法。

當調用成功時,打印出

{
  "name":"jack",
  "nationality":"china"
}

我們把 url 地址故意寫錯,調用失敗,將會報錯,顯示如下

Error: Not Found

Promise 是同步還是異步執行

再看個例子

console.log(1)
setTimeout(function(){
  console.log(2)
},0)
var promise =new Promise(function(resolve){
  resolve(3)
}).then(function(value){
  console.log(value)
})
console.log(4)

打印出1 4 3 2。

Promise 是異步執行的。有個問題,為什么 setTimeout 模擬異步會比 promise 晚出現呢?

這就涉及到 microtask 和 macrotask 問題。簡單說,promise 排在了異步下批執行的第一梯隊,而setTimeout 則排在第二梯隊。

Promise API

Promise.all 接收一個 promise對象的數組作為參數,當這個數組里的所有promise對象全部變為resolve或reject狀態的時候,它才會去調用 .then 方法。

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise(function(resolve) {
  setTimeout(resolve, 500, "foo");
});
Promise.all([p1, p2, p3]).then(function(value) {
  console.log(value); // [3, 1337, "foo"] 
});

Promise.race 接收一個 promise對象的數組作為參數,只要有一個promise對象進入 FulFilled 或者 Rejected 狀態的話,就會繼續進行后面的處理。

var p5 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 500, "five");
});
var p6 = new Promise(function(resolve, reject) {
  setTimeout(reject, 100, "six");
});
Promise.race([p5, p6]).then(function(value) {
  console.log(value)
}, function(reason) {
  console.log(reason); // "six"
  // p6 更快,所以它失敗了
});
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Promiese 簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果,語法上說,Pr...
    雨飛飛雨閱讀 3,373評論 0 19
  • 00、前言Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區...
    夜幕小草閱讀 2,139評論 0 12
  • 本文適用的讀者 本文寫給有一定Promise使用經驗的人,如果你還沒有使用過Promise,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,323評論 6 19
  • //本文內容起初摘抄于 阮一峰 作者的譯文,用于記錄和學習,建議觀者移步于原文 概念: 所謂的Promise,...
    曾經過往閱讀 1,251評論 0 7
  • Promise的含義: ??Promise是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和...
    呼呼哥閱讀 2,188評論 0 16