成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

簡單學(xué)習(xí) Promise 對象

muzhuyu / 2918人閱讀

摘要:方法是的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。由于字符串不屬于異步操作判斷方法是字符串對象不具有方法,返回實(shí)例的狀態(tài)從一生成就是,所以回調(diào)函數(shù)會(huì)立即執(zhí)行。出錯(cuò)了等同于出錯(cuò)了出錯(cuò)了上面的代碼生成一個(gè)對象的實(shí)例,狀態(tài)為,回調(diào)函數(shù)會(huì)立即執(zhí)行。

引言 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)和事件——更合理且強(qiáng)大。最近的項(xiàng)目要用到這個(gè),就參照阮一峰老師的《ES6標(biāo)準(zhǔn)入門》這本書簡單學(xué)一下了。

1 Promise 的含義

所謂 Promise ,簡單來說就是一個(gè)容器,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語法上來看,Promise 是一個(gè)對象,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理。

Promise 對象有以下兩個(gè)特點(diǎn)。

對象的狀態(tài)不受外界影響。

一旦狀態(tài)改變就不會(huì)再變。

2 基本用法

ES6 規(guī)定,Promise 對象是一個(gè)構(gòu)造函數(shù),用來生成 Promise 實(shí)例。
舉個(gè)例子。

var promise = new Promise(function (resolve, reject) {
  // some code
  if (/* 異步操作成功*/) {
     resolve(value);
  } else {
    // 異步操作失敗
    reject(error);
  }
});

Promise 構(gòu)造函數(shù)接收一個(gè)函數(shù)作為參數(shù),該函數(shù)的兩個(gè)參數(shù)分別是 resolvereject。他們是兩個(gè)函數(shù),由 Javascript 引擎提供,不用自己部署。

resolve 函數(shù)的作用是將 Promise 對象的狀態(tài)從『未完成』(Pending)變?yōu)椤撼晒Α唬≧esolved),在異步操作成功的時(shí)候調(diào)用,并將異步操作的結(jié)果作為參數(shù)傳遞過去。 reject 函數(shù)的作用是,將 Promise 對象的狀態(tài)從『未完成』(Pending)變?yōu)椤菏 唬≧ejected)

當(dāng)我們生成了一個(gè) Promise 實(shí)例之后。就可以用 then 方法分別指定 Resolved 狀態(tài)和 Rejected 狀態(tài)的回調(diào)函數(shù)。

promise.then(function (value) {
  // success
  console.log(value);
}, function (error) {
  // failed
  console.log(error);
});

then 方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。第一個(gè)回調(diào)函數(shù)是 Promise 對象的狀態(tài)變?yōu)?Resolved 時(shí)調(diào)用,第二個(gè)回調(diào)函數(shù)是 Promise 對象的狀態(tài)變?yōu)?Rejected 時(shí)調(diào)用。其中第二個(gè)參數(shù)是可選的,不一定要提供。這兩個(gè)函數(shù)都接收 Promise 對象傳出的值作為參數(shù)。

我們來個(gè)小例子

let promise = new Promise(function(resolve,reject){
  console.log("Promise");
  let value = "value";
  resolve(value);
});

promise.then(function(value){
  console.log(value);
});
console.log("Hi");

// Promise
// Hi
// value

上面的代碼中,Promise 新建后會(huì)立即執(zhí)行,所以首先輸出的是 Promise。然后,then 方法指定的回調(diào)函數(shù)將當(dāng)前腳本所有同步任務(wù)執(zhí)行完成后才會(huì)執(zhí)行,所以 Resolved 最后輸出。

3 Promise.prototype.then()

Promise 實(shí)例具有 then 方法,即 then 方法是定義在原型對象 Promise.prototype 上的。它的作用是為 Promise 實(shí)例添加改變狀態(tài)時(shí)的回調(diào)函數(shù)。前面說過,then 方法的第一個(gè)參數(shù)是 Resolved 狀態(tài)的回調(diào)函數(shù),第二個(gè)參數(shù)(可選)是 Rejected 狀態(tài)的回調(diào)函數(shù)。

then 方法返回的是一個(gè)新的 Promise 實(shí)例注意 不是原來的那個(gè) Promise 實(shí)例)。因此可以采用鏈?zhǔn)綄懛ǎ?then 方法后面再調(diào)用另一個(gè) then 方法。

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
    // ...
});

上面的代碼使用 then 方法依次指定了兩個(gè)回調(diào)函數(shù)。第一個(gè)回調(diào)函數(shù)完成以后,將會(huì)返回結(jié)果作為參數(shù),傳入第二個(gè)回調(diào)函數(shù)。

然后采用鏈?zhǔn)降?then 可以指定一組按順序調(diào)用的回調(diào)函數(shù)。這時(shí),前一個(gè)回調(diào)函數(shù)有可能返回的還是一個(gè) Promise 對象(即有異步操作),而后一個(gè)回調(diào)函數(shù)就會(huì)等待該 Promise 對象的狀態(tài)發(fā)生變化,再被調(diào)用。

4 Promise.prototype.catch()

Promise.prototype.catch 方法是 .then(null, rejection) 的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。

getJSON("/posts.json").then(function(posts) {
  // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤
  console.log("發(fā)生錯(cuò)誤!", error);
});

上面的代碼中,getJSON 方法返回一個(gè) Promise 對象,如果該對象狀態(tài)變?yōu)?Resolved,則會(huì)調(diào)用 then 方法指定的回調(diào)函數(shù);如果異步操作拋出錯(cuò)誤,狀態(tài)就會(huì)變成 Rejected,然后調(diào)用 catch 方法指定的回調(diào)函數(shù)處理這個(gè)錯(cuò)誤。另外, then 方法指定的回調(diào)函數(shù)如果在運(yùn)行中拋出錯(cuò)誤,也會(huì)被 catch 方法捕獲。

p.then((val) => console.log("fulfilled:", val))
  .catch((err) => console.log("rejected", err));

  // 等同于
  p.then((val) => console.log("fulfilled:", val))
  .then(null, (err) => console.log("rejected:", err));

下面是一個(gè)例子。

const promise = new Promise(function(resolve, reject) {
  throw new Error("test");
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

上面的代碼中,Promise 拋出一個(gè)錯(cuò)誤就被 catch 方法指定的回調(diào)函數(shù)所捕獲。注意,上面的寫法和下面兩種寫法是等價(jià)的。

// 寫法一
const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error("test");
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 寫法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error("test"));
});
promise.catch(function(error) {
  console.log(error);
});

由上面可以看出, reject 方法的作用等同于拋出錯(cuò)誤。
如果 Promise 狀態(tài)已經(jīng)變成 Resolved,在拋出錯(cuò)誤是無效的。

const promise = new Promise(function(resolve, reject) {
  resolve("ok");
  // Promise 狀態(tài)已變成 已完成
  throw new Error("test");
});
promise
  .then(function(value) { console.log(value) })
  .catch(function(error) { console.log(error) });
// ok

注意 一般來說,不要在 then 方法中定義 Reject 狀態(tài)的回調(diào)函數(shù)(即 then 的第二個(gè)參數(shù)),而是使用 catch 方法。

// bad
promise
  .then(function(data) {
  // success
  }, function(err) {
  // error
});

// good
promise
  .then(function(data) { //cb
  // success
  })
  .catch(function(err) {
  // error
  });

上面代碼中,第二種寫法要好于第一種寫法,理由是第二種寫法可以捕獲前面 then 方法執(zhí)行中的錯(cuò)誤,也更接近同步的寫法(try/catch)。因此,建議總是使用 catch 方法,而不使用 then 方法的第二個(gè)參數(shù)。

5 Promise.all()

Promise.all 方法是將多個(gè) Promise 對象實(shí)例包裝成一個(gè)新的實(shí)例。

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

上面的代碼中,Promise.all() 方法接受一個(gè)數(shù)組作為參數(shù),p1, p2, p3 都是 Promise 對象的實(shí)例。如果不是,就會(huì)先調(diào)用下面講到的 Promise.resolve 方法,將參數(shù)轉(zhuǎn)換為 Promise 實(shí)例,再進(jìn)一步處理(Promise.all 方法的參數(shù)不一定是數(shù)組,但是必須具有 Iterator 接口,且每個(gè)返回成員都是 Promise 實(shí)例)。

p 的狀態(tài)由 p1, p2, p3 決定,分成兩種情況

只有 p1, p2, p3 的狀態(tài)都變成 FulFilled,p 的狀態(tài)才會(huì)變成 FulFilled,此時(shí) p1, p2, p3 的返回值組成一個(gè)數(shù)組,傳遞給 p 的回調(diào)函數(shù)。

只要 p1,p2,p3 中有一個(gè)被 Rejected ,p 的狀態(tài)就直接變成 Rejected,此時(shí)第一個(gè)被 Rejected 的實(shí)例的返回值會(huì)傳遞給 p 的回調(diào)函數(shù)。

下面是一個(gè)具體例子。

var promises = [2,3,4,5].map(function(id){
      console.log(id)
    });
    
    Promise.all(promises).then(function(res){
      console.log(res);
      resolve
    }).catch(function(error){
      console.log(error);
    });

// 先執(zhí)行所有 promise 實(shí)例的異步操作,然后吧操作的結(jié)果打包數(shù)組返回
// 2 3 4 5 [undefined,undefined,undefined,undefined]

上面的代碼中,Promise 是包含 6 個(gè) Promise 實(shí)例的數(shù)組,只有這 6 個(gè)實(shí)例的狀態(tài)都變成 fulfilled,或者其中有 1 個(gè)變成 rejected,才會(huì)調(diào)用 Promise.all 方法后面的回調(diào)函數(shù)。

6 Promise.race()

Promise.race 方法同樣是將多個(gè) Promise 實(shí)例包裝成一個(gè)新的 Promise 實(shí)例。

var p = Promise.race([p1, p2, p])

上面的代碼中,只要 p1, p2, p3 中 有一個(gè)實(shí)例 率先改變狀態(tài),p 的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise 實(shí)例的返回值就傳遞給 p 的回調(diào)函數(shù)。
Promise.race 方法的參數(shù)與 Promise.all 方法一樣,如果不是 Promise 實(shí)例,就會(huì)先調(diào)用下面講到的 Promise.resolve 方法,將參數(shù)轉(zhuǎn)為 Promise 實(shí)例,再進(jìn)一步處理。

下面是一個(gè)例子,如果指定時(shí)間內(nèi)沒有獲得結(jié)果,就將 Promise 的狀態(tài)變成 Rejected,否則就變?yōu)?Resolved。

const p = Promise.race([
  fetch("/resource-that-may-take-a-while"),
  new Promise(function (resolve, reject) {
    setTimeout(() => reject(new Error("request timeout")), 5000)
  })
]);

p
.then(console.log)
.catch(console.error);

上面代碼中,如果 5 秒之內(nèi) fetch 方法無法返回結(jié)果,變量 p 的狀態(tài)就會(huì)變?yōu)?rejected,從而觸發(fā) catch 方法指定的回調(diào)函數(shù)。

7 Promise.resolve()

有時(shí)需要將現(xiàn)有對象轉(zhuǎn)為 Promise 對象,Promise.resolve 方法就起到這個(gè)作用。

const jsPromise = Promise.resolve($.ajax("/whatever.json"));

上面代碼將 jQuery 生成的 deferred 對象,轉(zhuǎn)為一個(gè)新的 Promise 對象。

Promise.resolve 等價(jià)于下面的寫法。

Promise.resolve("foo")
// 等價(jià)于
new Promise(resolve => resolve("foo"))

Promise.resolve方法的參數(shù)分成四種情況。

7.1 參數(shù)是一個(gè) Promise 實(shí)例

如果參數(shù)是一個(gè) Promise 實(shí)例,那么 Promise.resolve 將不做任何修改,原封不動(dòng)的返回這個(gè)實(shí)例。

7.2 參數(shù)是一個(gè) thenable 對象

thenable 對象是指具有 then 方法的對象,例如下面這個(gè)對象

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

Promise.resolve 方法會(huì)將這個(gè)對象轉(zhuǎn)為 Promise 對象,任何執(zhí)行 thenable 對象的 then 方法。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
};

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

上面的代碼中, thenable 對象的 then 方法執(zhí)行后,對象 p1 的狀態(tài)就變?yōu)?resolved,從而立即執(zhí)行最后的 then 方法指定的回調(diào)函數(shù)。輸出 42。

7.3 參數(shù)不是具有 then 方法的對象,或根本就不是對象

如果參數(shù)是一個(gè)原始值,或者是一個(gè)不具有 then 方法的對象,那么 Promise.resolved 方法返回一個(gè)新的 Promise 對象,狀態(tài)為 Resolved。

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

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

上面代碼生成一個(gè)新的 Promise 對象的實(shí)例 p。由于字符串 Hello 不屬于異步操作(判斷方法是字符串對象不具有 then 方法),返回 Promise 實(shí)例的狀態(tài)從一生成就是 resolved,所以回調(diào)函數(shù)會(huì)立即執(zhí)行。Promise.resolve 方法的參數(shù),會(huì)同時(shí)傳給回調(diào)函數(shù)。

7.4 不帶有任何參數(shù)

Promise.resolved 方法允許在調(diào)用時(shí)不帶有參數(shù),而直接返回一個(gè) Resolved 狀態(tài)的 Promise 對象。

所以,如果你希望得到一個(gè) Promise 對象,比較方便的方法就是直接調(diào)用 Promise.resolve 方法。

const p = Promise.resolve();

p.then(function () {
  // ...
});

上面代碼中的 p 就是一個(gè) Promise 對象。
需要注意的是,立即 resolve 的 Promise 對象實(shí)在本輪 『事件循環(huán)』(event loop)結(jié)束時(shí),而不是在下一輪『事件循環(huán)』開始時(shí)。

setTimeout(function () {
  console.log("three");
}, 0);

Promise.resolve().then(function () {
  console.log("two");
});

console.log("one");

// one
// two
// three

上面代碼中,setTimeout(fn, 0) 在下一輪『事件循環(huán)』開始時(shí)執(zhí)行,Promise.resolve() 在本輪『事件循環(huán)』結(jié)束時(shí)執(zhí)行,console.log("one") 則是立即執(zhí)行,因此最先輸出。

8 Promise.reject()

Promise.reject(resson) 方法也會(huì)返回一個(gè)新的 Promise 實(shí)例,狀態(tài)為 Rejected (這個(gè)就暫時(shí)想不懂怎么應(yīng)用了)。

const p = Promise.reject("出錯(cuò)了");
// 等同于
const p = new Promise((resolve, reject) => reject("出錯(cuò)了"))

p.then(null, function (s) {
  console.log(s)
});
// 出錯(cuò)了

上面的代碼生成一個(gè) Promise 對象的實(shí)例 p,狀態(tài)為 Rejected,回調(diào)函數(shù)會(huì)立即執(zhí)行。

總結(jié)

以上就是關(guān)于 Promise 學(xué)習(xí)的內(nèi)容,如有錯(cuò)誤的地方就請?jiān)谙旅嬖u(píng)論處,發(fā)表一下看法,當(dāng)然也可以放一下關(guān)于進(jìn)階學(xué)習(xí) Promise 的文章,大家一起學(xué)習(xí)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99982.html

相關(guān)文章

  • Promise源碼學(xué)習(xí)(1)

    摘要:工作當(dāng)中經(jīng)常會(huì)用到,在此進(jìn)行深入學(xué)習(xí)異步編程解決方案是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。所有源碼注釋見學(xué)習(xí)筆記 工作當(dāng)中經(jīng)常會(huì)用到Promise,在此進(jìn)行深入學(xué)習(xí) 異步編程解決方案 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了...

    young.li 評(píng)論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會(huì)promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評(píng)論0 收藏0
  • Promise學(xué)習(xí):基礎(chǔ)入門

    摘要:今天來學(xué)習(xí)下吧其實(shí)這在筆試上也是一個(gè)考點(diǎn)基本介紹對象是熟悉的名字吧工作組提出的規(guī)范原本只是社區(qū)提出的構(gòu)想一些外部函數(shù)庫率先實(shí)現(xiàn)了該功能中將其寫入了語言標(biāo)準(zhǔn)目的為異步操作提供統(tǒng)一接口是啥它就是一個(gè)中一個(gè)對象起著代理作用充當(dāng)異步操作與回調(diào)函 今天來學(xué)習(xí)下Promise吧,其實(shí)這在筆試上也是一個(gè)考點(diǎn). 基本介紹 Promise對象是CommonJS(熟悉的名字吧- -)工作組提出的規(guī)范.Pr...

    iamyoung001 評(píng)論0 收藏0
  • [es6系列]學(xué)習(xí)Promise

    摘要:概述在之前,在中的異步編程都是采用回調(diào)函數(shù)和事件的方式,但是這種編程方式在處理復(fù)雜業(yè)務(wù)的情況下,很容易出現(xiàn)回調(diào)地獄,使得代碼很難被理解和維護(hù)。如果不設(shè)置回調(diào)函數(shù),內(nèi)部的錯(cuò)誤不會(huì)反應(yīng)到外部。 本文是基于對阮一峰的Promise文章的學(xué)習(xí)整理筆記,整理了文章的順序、增加了更多的例子,使其更好理解。 1. 概述 在Promise之前,在js中的異步編程都是采用回調(diào)函數(shù)和事件的方式,但是這種編...

    YanceyOfficial 評(píng)論0 收藏0
  • JavaScript 異步

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。寫一個(gè)符合規(guī)范并可配合使用的寫一個(gè)符合規(guī)范并可配合使用的理解的工作原理采用回調(diào)函數(shù)來處理異步編程。 JavaScript怎么使用循環(huán)代替(異步)遞歸 問題描述 在開發(fā)過程中,遇到一個(gè)需求:在系統(tǒng)初始化時(shí)通過http獲取一個(gè)第三方服務(wù)器端的列表,第三方服務(wù)器提供了一個(gè)接口,可通過...

    tuniutech 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<