ES6學(xué)習(xí)筆記(16)之 Promise

參考:ECMAScript 6 入門

promise對象的特點(diǎn):

  • 對象的狀態(tài)不受外界影響,只能內(nèi)部決定。(三種狀態(tài):pending, fulfilled, rejected)
  • 一旦狀態(tài)改變,就不會再變。
const promise = new Promise(function(resolve, reject) {
  resolve('ok');
  throw new Error('test');
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok
  • 一旦新建它就會立即執(zhí)行,無法中途取消。
  • 跟傳統(tǒng)的try/catch代碼塊不同的是,如果沒有使用catch方法指定錯誤處理的回調(diào)函數(shù),Promise 對象拋出的錯誤不會傳遞到外層代碼,即不會有任何反應(yīng)。(也就是說,即使promise內(nèi)部有錯誤,程序也不會崩潰;想想其它的錯誤,如果不被catch住,程序就報錯中斷了)
const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,因為x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123
  • 調(diào)用resolve或reject并不會終結(jié) Promise 的函數(shù)的執(zhí)行。
new Promise((resolve, reject) => {
  resolve(1); // 最好在此處return,比如:return resolve(1);
  console.log(2);
}).then(r => {
  console.log(r);
});
console.log(3);
// 2
// 3
// 1
  • resolve函數(shù)的參數(shù)除了正常的值以外,還可能是另一個 Promise 實(shí)例
const p1 = new Promise(function (resolve, reject) {
  setTimeout(() => reject(new Error('fail')), 3000)
})

const p2 = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(p1), 1000)
})

p2
  .then(result => console.log(result))
  .catch(error => console.log(error))
// Error: fail

解釋:(我的理解:then方法只接受確定的狀態(tài)?)

p1是一個 Promise,3 秒之后變?yōu)閞ejected。p2的狀態(tài)在 1 秒之后改變,resolve方法返回的是p1。由于p2返回的是另一個 Promise,導(dǎo)致p2自己的狀態(tài)無效了,由p1的狀態(tài)決定p2的狀態(tài)。所以,后面的then語句都變成針對后者(p1)。又過了 2 秒,p1變?yōu)閞ejected,導(dǎo)致觸發(fā)catch方法指定的回調(diào)函數(shù)。

  • then方法返回的是一個新的Promise實(shí)例
getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL); // 又返回一個promise對象,該對象的返回結(jié)果將在下一個then中處理
}).then(function (comments) {
  console.log("resolved: ", comments);
}).catch(function (err){ 
//該catch方法有可能捕獲第一個promise對象的錯誤,也有可能捕獲第二個promise的錯誤
//Promise 對象的錯誤具有“冒泡”性質(zhì),會一直向后傳遞,直到被捕獲為止。也就是說,錯誤總是會被下一個catch語句捕獲。
  console.log("rejected: ", err);
});

promise的幾個API的介紹:

Promise.prototype.finally()

  • ES2018(ES9)的標(biāo)準(zhǔn),ES6中還沒有。
  • 無論成功失敗都執(zhí)行的操作。

Promise.all()

  • Promise.all方法的參數(shù)可以是數(shù)組,比如Promise.all([p1, p2, p3])
  • p1、p2、p3都是 Promise 實(shí)例,如果不是,就會先調(diào)用Promise.resolve方法,將參數(shù)轉(zhuǎn)為 Promise 實(shí)例,再進(jìn)一步處理。
  • 參數(shù)也可以是具有 Iterator 接口的對象,且返回的每個成員都是 Promise 實(shí)例。
  • p1, p2, p3都成功時all方法才成功,只要有一個失敗,all方法就失敗。

Promise.race()

  • 參數(shù)要求同Promise.all()
  • p1, p2, p3誰先執(zhí)行完有結(jié)果,race 的 then(或catch)方法就執(zhí)行誰的,這就體現(xiàn)出了賽跑的特點(diǎn)。

Promise. resolve()

  • 將現(xiàn)有對象轉(zhuǎn)為 Promise 對象
  • 可以接受什么參數(shù)呢?
    1)如果參數(shù)是 Promise 實(shí)例,那么Promise.resolve將不做任何修改、原封不動地返回這個實(shí)例。
    2)如果參數(shù)是一個thenable對象。thenable對象指的是具有then方法的對象,比如下面這個對象。
let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

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

3)參數(shù)為一般的對象,或根本不是對象。作為返回值返回。(如果參數(shù)為空,可以認(rèn)為返回undefined)

const p = Promise.resolve('Hello');

p.then(function (s){
  console.log(s)
});
// Hello

Promise. reject()

  • Promise. resolve()的不同:
    Promise.reject()方法的參數(shù),會原封不動地作為reject的理由,變成后續(xù)方法的參數(shù)
const thenable = {
  then(resolve, reject) {
    reject('出錯了');
  }
};

Promise.reject(thenable)
.catch(e => {
  console.log(e === thenable)
})
// true

Promise.try()
作用:將同步異步方法統(tǒng)一處理,可以更好地管理異常。

function getUsername(userId) {
  return database.users.get({id: userId})
  .then(function(user) {
    return user.name;
  });
}

上面代碼中,database.users.get()返回一個 Promise 對象,如果拋出異步錯誤,可以用catch方法捕獲,就像下面這樣寫。

database.users.get({id: userId})
.then(...)
.catch(...)

但是database.users.get()可能還會拋出同步錯誤(比如數(shù)據(jù)庫連接錯誤,具體要看實(shí)現(xiàn)方法),這時你就不得不用try...catch去捕獲。

try {
  database.users.get({id: userId})
  .then(...)
  .catch(...)
} catch (e) {
  // ...
}

上面這樣的寫法就很笨拙了,這時就可以統(tǒng)一用promise.catch()捕獲所有同步和異步的錯誤。

Promise.try(() => database.users.get({id: userId}))
  .then(...)
  .catch(...)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,823評論 1 56
  • 1. Promise 的含義 所謂Promise,簡單說就是一個容器,里面保存著某個未來才會結(jié)束的事件(通常是一個...
    ROBIN2015閱讀 580評論 0 0
  • //本文內(nèi)容起初摘抄于 阮一峰 作者的譯文,用于記錄和學(xué)習(xí),建議觀者移步于原文 概念: 所謂的Promise,...
    曾經(jīng)過往閱讀 1,315評論 0 7
  • 原文地址:http://es6.ruanyifeng.com/#docs/promise Promise 的含義 ...
    AI云棧閱讀 974評論 0 7
  • 『ES6腳丫系列』Promise Promise 文本主要內(nèi)容如下: * Promise是什么? * 1.1 特點(diǎn)...
    吃碼小妖閱讀 1,052評論 0 12

友情鏈接更多精彩內(nèi)容