Promise詳解

什么是promise

ES6異步編程的一種解決方案,將異步操作以同步的方式表達出來,避免層層嵌套的回調函數

為什么要用promise

  1. 指定回調函數的方式更加靈活
  • 使用純回調函數方式,必須在異步任務執行前指定回調函數
// 成功的回調函數
function successCallback(result) {
  console.log("音頻文件創建成功: " + result);
}

// 失敗的回調函數
function failureCallback(error) {
  console.log("音頻文件創建失敗: " + error);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback)
  • promise 可以在啟動異步任務后指定回調函數,甚至可以在異步任務結束后綁定回調函數
const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);

setTimeout(() => {
  promise.then(successCallback, failureCallback);
 },2000)
  1. 支持鏈式調用,解決回調地獄
    回調地獄:回調函數嵌套調用,外部回調函數異步執行的結果,是嵌套的回調函數執行的條件
    嵌套的回調函數不便于閱讀、不便于異常處理
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

Promise 鏈式調用

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

promise鏈式調用異常傳遞

new Promise((resolve,reject) => {
  reject(1)
}).then(
  value => {
    console.log('onResolved',value)
    return 2
  },
  // error => { throw error } 
  // error => Promise.reject(error) 
).then(
  value => {
    console.log('onResolved',value)
    return 3
  },
  // error => { throw error } 
).catch(reason => {
  console.log('onRejected',reason)
})
輸出:onReject 1

一遇到異常拋出,瀏覽器就會順著 Promise 鏈尋找下一個 onRejected 失敗回調函數或者由 .catch() 指定的回調函數,相當于注釋代碼的兩種寫法之一

中斷promise鏈

new Promise((resolve, reject) => {
    reject(1);
})
.then(() => {
    console.log(2);
})
.catch(() => {
    console.log(3);
    //要中斷catch()后面的then()方法,
  return new Promise(() => {}); //返回一個padding的promise
})
.then(() => {
    console.log(3);
});

promise的特點

  • 對象的狀態不受外界影響。Promise對象代表一個異步操作,有三種狀態:pending(進行中)、resolved(已成功)和rejected(已失敗)

  • 一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態改變,只有兩種可能:從pending變為resolved和從pending變為rejected

  • promise內部發生錯誤,不會影響到外部程序的執行。

  • 無法取消Promise。一旦新建它就會立即執行,無法中途取消。其次,如果不設置回調函數,Promise內部拋出的錯誤,不會反應到外部。第三,當處于pending狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)

用法

創造promise 實例時,必須傳入一個函數作為參數

new promise(() => {});

該函數可以接收另外兩個由JavaScript引擎提供的函數,resolve和reject。函數作用:

  • resolve——將Promise對象的狀態從pending變為resolved,將異步操作的結果,作為參數傳遞出去
  • reject——將Promise對象的狀態從pending變為rejected,將異步操作報出的錯誤,作為參數傳遞出去
let promise = new promise((resolve, reject) => {
  //do something
  if(true){
    //將參數返回,供then方法使用
    resolve('value');
  }else {
    reject('error');
  }
});

promise 實例方法

promise.prototype.then()

Promise實例生成以后,可以用then方法分別指定resolved狀態和rejected狀態的回調函數。then方法返回的是一個新的Promise實例

promise.then(
  //resolved時調用,value為resolve函數返回的參數
  value => {
    console.log(value);
  },
  err => {
    //reject時調用
    console.log(err);
  }
 );

當then方法只有一個函數參數時,此時為resolved狀態的回調方法

 promise .then(value => {
    console.log(value);
  })
  .catch(err => {
    //
}
`推薦這種方式,可以捕獲前面then方法執行中的錯誤

Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的別名
Promise 新建后就會立即執行,并且調用resolve或reject后不會終結 Promise的參數函數的執行。

let promise = new Promise(function(resolve){
   console.log('promise');
   resolve();
   console.log(1)
})
promise.then(function() {
   console.log('resolved');
})
console.log(2)
//promise
//1
//2
//resolved

Promise.then()返回的promise狀態是什么?

由then()指定的回調函數的執行結果決定
1、如果拋出異常,返回的promise變為rejected,error為拋出的異常
2、如果返回非promise的任意值,返回的promise變為resolved狀態,value為返回的值
3、如果返回另一個新的promise,此promise的結果就是返回的promise的結果

const p = new Promise(function(resolve,rejected){
  resolve(1)
})
p.then(value => {
  //情況1:拋出異常
  throw '錯誤'

  //2.返回一個值
  return value+1;

  //3.返回一個Promise
  return new Promise((resolve, reject) => {
    resolve(value+2)
  });
  return new Promise((resolve, reject) => {
    reject(value+3)
  });

  //4.沒有返回值
  相當于 return undefined

}).then(value => {
  console.log('onResolved',value);
},error => {
  console.log('onRejected',error)
});
  1. 拋出的異常將作為then方法返回的promise的reject的值傳遞出
    輸出: onRejected 錯誤
  1. return的值將作為then方法返回的promise的resolve的值傳遞出
    輸出: onResolved 2
  1. return 的promise的結果將作為then方法返回的promise的結果
    分別輸出: onResolved 3 ,onRejected 4
  1. 構造then方法的函數沒有向then方法返回的promise對象的resolve方法傳遞值。因此resolve返回的是undefined
    輸出: onResolved undefined
  • promise.catch()
  • promise.finally() 無論成功失敗都執行

靜態api方法

promise.all() 將多個 Promise 實例,包裝成一個新的 Promise 實例

const p =Promise.all([p1, p2, p3]);

p1,p2,p3都是Promise實例;p的狀態由p1、p2、p3決定,分成兩種情況。

(1)只有p1、p2、p3的狀態都變成fulfilled,p的狀態才會變成fulfilled,此時p1、p2、p3的返回值組成一個數組,傳遞給p的回調函數。

(2)只要p1、p2、p3之中有一個被rejected,p的狀態就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調函數。

promise.race()方法是將多個Promise實例包裝為一個實例

const p = Promise.race([p1, p2, p3]);

上面代碼中,只要p1、p2、p3之中有一個實例率先改變狀態,p的狀態就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調函數。

Promise.resolve()
Promise.resolve(1)
// 等價于
new Promise(resolve => resolve(1))

Promise.resolve()方法的參數:

  1. 參數是promise實例
    返回這個實例
  2. 參數是一個thenable對象
    thenable對象指的是具有then方法的對象
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

let p1 = Promise.resolve(thenable);
p1.then(function (value) {
  console.log(value);  // 42
});

Promise.resolve()方法會將這個對象轉為 Promise 對象,然后就立即執行thenable對象的then()方法。

  1. 參數不是具有then()方法的對象,或根本就不是對象
    如果參數是一個原始值,或者是一個不具有then()方法的對象,則Promise.resolve()方法返回一個新的 Promise 對象,狀態為resolved。
const p = Promise.resolve('Hello');
p.then(function (s) {
  console.log(s)
});
//hello
  1. 不帶任何參數
    直接返回一個resolved狀態的 Promise 對象。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Promiese 簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果,語法上說,Pr...
    雨飛飛雨閱讀 3,368評論 0 19
  • 摘自:阮一峰 http://es6.ruanyifeng.com/#docs/promise 一、首先,我們要弄明...
    泡杯感冒靈閱讀 805評論 0 4
  • 00、前言Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區...
    夜幕小草閱讀 2,137評論 0 12
  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函...
    neromous閱讀 8,723評論 1 56
  • 一、Promise的含義 Promise在JavaScript語言中早有實現,ES6將其寫進了語言標準,統一了用法...
    Alex灌湯貓閱讀 837評論 0 2