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

資訊專欄INFORMATION COLUMN

Promise——從閱讀文檔到簡(jiǎn)單實(shí)現(xiàn)(一)

yanwei / 1841人閱讀

摘要:意味著操作成功完成。方法接收失敗情況的回調(diào)函數(shù)作為參數(shù),返回一個(gè)對(duì)象。參數(shù)回調(diào)函數(shù)不接收任何參數(shù),當(dāng)對(duì)象變成狀態(tài)時(shí)被調(diào)用?,F(xiàn)在各個(gè)方法的參數(shù)返回值功能和使用方法已經(jīng)有個(gè)大概的了解了,為了進(jìn)一步理解其原理,接下來我打算簡(jiǎn)單地實(shí)現(xiàn)一下它。

前言

最近幾周參加筆試面試,總是會(huì)遇到實(shí)現(xiàn)異步和處理異步的問題,然而作者每次都無法完美地回答。在最近一次筆試因?yàn)?Promise 而被刷掉后,我終于下定決心一個(gè)個(gè)地搞懂它們,就先拿 Promise 開刀吧 :)。

用法解析

ES6 的Promise對(duì)象是一個(gè)代理對(duì)象,被代理的值在Promise對(duì)象創(chuàng)建時(shí)可能是未知的,另外它允許你為異步操作的成功和失敗分別綁定相應(yīng)的處理方法。
Promise 常用于控制異步操作的執(zhí)行順序,而且可以讓異步方法像同步方法那樣返回值。它不能立即取得異步方法的返回值,但是它可以代理這個(gè)值,一旦異步操作完成,就會(huì)以及將值傳遞給相應(yīng)的處理方法。
一個(gè)Promise對(duì)象有以下幾種狀態(tài):

pending: 初始狀態(tài),既不是成功,也不是失敗狀態(tài)。

fulfilled: 意味著操作成功完成。

rejected: 意味著操作失敗。

一個(gè)Promise對(duì)象的狀態(tài)可以從pending變成fulfilled,同時(shí)傳遞一個(gè)值給相應(yīng)的onfulfilled處理方法;也可以從pending變成rejected,同時(shí)傳遞一個(gè)失敗信息給相應(yīng)的onrejected處理方法。
一旦一個(gè)Promise對(duì)象的狀態(tài)發(fā)生改變,就會(huì)觸發(fā)之前通過Promise.prototype.then、 Promise.prototype.catch和 Promise.prototype.finally方法綁定的onfulfilled、onrejectedonFinally處理方法。
因?yàn)?then、catchfinally方法都會(huì)返回一個(gè)新的Promise對(duì)象, 所以它們可以被鏈?zhǔn)秸{(diào)用。

構(gòu)造函數(shù)

構(gòu)造函數(shù)Promise()主要用來包裝還未支持 promises 的函數(shù)。

new Promise( function(resolve, reject) {...} /* executor */  );

參數(shù):executor
executor是帶有 resolvereject 兩個(gè)函數(shù)參數(shù)的函數(shù)。Promise構(gòu)造函數(shù)執(zhí)行時(shí)立即調(diào)用executor函數(shù),換句話說,executor函數(shù)是在Promise構(gòu)造函數(shù)內(nèi)執(zhí)行的,所以它是同步代碼。在executor函數(shù)內(nèi)調(diào)用 resolvereject 函數(shù),可以傳遞參數(shù)給相應(yīng)的處理方法,并會(huì)分別將 promise 新建對(duì)象的狀態(tài)改為fulfilled(完成)或rejected(失敗)。
executor 內(nèi)部通常會(huì)執(zhí)行一些異步操作如ajax,一旦完成,可以調(diào)用resolve函數(shù)傳遞參數(shù)并將 promise 對(duì)象的狀態(tài)改成 fulfilled,或者在發(fā)生錯(cuò)誤時(shí)調(diào)用reject 函數(shù)傳遞參數(shù)并將 promise 對(duì)象的狀態(tài)改成 rejected。如下:

function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
};

如果在executor函數(shù)中拋出一個(gè)錯(cuò)誤,那么該 promise 對(duì)象狀態(tài)將變?yōu)?b>rejected,并將錯(cuò)誤作為參數(shù)傳遞給對(duì)應(yīng)的onrejected處理方法。如下:

function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onerror = () => {
        throw xhr.statusText;
        //throw xhr.statusText 效果等同于 reject(xhr.statusText)
    };
    xhr.send();
  });
};
靜態(tài)方法

靜態(tài)方法是定義在構(gòu)造函數(shù)上的方法,聲明靜態(tài)方法:

Func.fn = function() {}

調(diào)用靜態(tài)方法:

Func.fn(args);

ES6中的Promise構(gòu)造函數(shù)有4個(gè)靜態(tài)方法:

Promise.resolve(value)

Promise.reject(reason)

Promise.all(iterable)

Promise.race(iterable)

Promise.resolve(value):
返回一個(gè)由參數(shù)value解析而來的Promise對(duì)象。

如果傳入的value本身就是Promise對(duì)象,則直接返回value

如果value是一個(gè)thenable對(duì)象(帶有 then 方法的對(duì)象),返回的Promise對(duì)象會(huì)跟隨這個(gè)thenable對(duì)象,狀態(tài)隨之變化;

其它情況下返回的Promise對(duì)象狀態(tài)為fulfilled,并且將該value作為參數(shù)傳遞給onfulfilled處理方法。

通常而言,如果你不知道一個(gè)值是否為Promise對(duì)象,就可以使用 Promise.resolve(value) 來將valuePromise對(duì)象的形式使用。

    // resolve一個(gè)thenable對(duì)象
    var p1 = Promise.resolve({ 
      then: function(onFulfill, onReject) { onFulfill("fulfilled!"); }
    });
    console.log(p1 instanceof Promise) // true, 這是一個(gè)Promise對(duì)象
    
    p1.then(function(v) {
        console.log(v); // 輸出"fulfilled!"
      }, function(e) {
        // 不會(huì)被調(diào)用
    });

Promise.reject(reason):
返回一個(gè)被給定原因reason拒絕的Promise對(duì)象。
返回的Promise對(duì)象的status狀態(tài)屬性為rejectedreason拒絕原因?qū)傩裕▊鬟f給onrejected處理方法的 reason 參數(shù))與參數(shù)reason相等。

Promise.reject(new Promise((resolve, reject) => resolve("done")))
.then(function(reason) {
      // 未被調(diào)用
}, function(reason) {
      console.log(reason); // new Promise
});

Promise.all(iterable):
參數(shù):iterable對(duì)象為Array對(duì)象、Map對(duì)象和Set對(duì)象等可迭代對(duì)象。
返回:一個(gè)Promise對(duì)象。

如果iterable不是一個(gè)可迭代對(duì)象,Promise.all會(huì)同步地返回返回一個(gè)狀態(tài)為rejected ,拒絕原因reson為類型錯(cuò)誤的 promise 對(duì)象;

如果iterable對(duì)象為空,Promise.all會(huì)同步地返回一個(gè)狀態(tài)為fulfilledvalue值為空數(shù)組的 promise 對(duì)象;

如果iterable對(duì)象中的 promise 對(duì)象都變?yōu)?b>fulfilled狀態(tài),或者iterable對(duì)象內(nèi)沒有 promise 對(duì)象,Promise.all返回的 promise 對(duì)象將異步地變?yōu)?b>fulfilled狀態(tài)。這兩種情況返回的 promise 對(duì)象的value值(傳遞給onfulfilled處理方法的 value 參數(shù))都是一個(gè)數(shù)組,這個(gè)數(shù)組包含iterable對(duì)象中所有的基本值和 promise 對(duì)象value值,這些值將會(huì)按照參數(shù)iterable內(nèi)的順序排列,而不是由 promise 的完成順序決定;

如果iterable對(duì)象中任意一個(gè) promise 對(duì)象狀態(tài)變?yōu)?b>rejected,那么Promise.all就會(huì)異步地返回一個(gè)狀態(tài)為rejected的 promise 對(duì)象,而且此 promise 對(duì)象的reason值(傳遞給onrejected處理方法的 reason 參數(shù)),等于iterable對(duì)象中狀態(tài)為rejected的那一個(gè) promise 對(duì)象的reason值。

    // this will be counted as if the iterable passed is empty, so it gets fulfilled
    var p = Promise.all([1,2,3]);
    // this will be counted as if the iterable passed contains only the resolved promise with value "333", so it gets fulfilled
    var p2 = Promise.all([1,2,3, Promise.resolve(333)]);
    // this will be counted as if the iterable passed contains the rejected promise with value "444", so it gets rejected
    var p3 = Promise.all([1,2, Promise.reject(444), Promise.reject(555)]);
    
    // using setTimeout we can execute code after the stack is empty
    setTimeout(function(){
        console.log(p);
        console.log(p2);
        console.log(p3);
    });
    
    // logs
    // Promise { : "fulfilled", : Array[3] }
    // Promise { : "fulfilled", : Array[4] }
    // Promise { : "rejected", : 444 }

Promise.race(iterable):
返回一個(gè)Promise對(duì)象。

如果iterable不是一個(gè)可迭代對(duì)象,Promise.race會(huì)同步地返回返回一個(gè)狀態(tài)為rejected,拒絕原因reson為類型錯(cuò)誤的 promise 對(duì)象;

如果iterable對(duì)象為空,Promise.all會(huì)同步地返回一個(gè)狀態(tài)為fulfilled,value值為空數(shù)組的 promise 對(duì)象;

如果iterable對(duì)象不為空,一旦iterable中的某個(gè) promise 對(duì)象完成或拒絕,返回的 promise 對(duì)象就會(huì)完成或拒絕,且返回的 promise 對(duì)象的value值(完成時(shí))或reason值(拒絕時(shí))和這個(gè) promise 對(duì)象的value值(完成時(shí))或reason值(拒絕時(shí))相等。

    var promise1 = new Promise(function(resolve, reject) {
        setTimeout(resolve, 500, "one");
    }), promise2 = new Promise(function(resolve, reject) {
        setTimeout(resolve, 100, "two");
    });
    
    Promise.race([promise1, promise2]).then(function(value) {
      console.log(value);
      // Both resolve, but promise2 is faster
    });
    // expected output: "two"
實(shí)例方法

實(shí)例方法是定義在原型對(duì)象上的方法,聲明實(shí)例方法:

Func.prototype.fn = function() {}

調(diào)用實(shí)例方法需要先創(chuàng)建一個(gè)實(shí)例:

let func = new Func();
func.fn(args);

Promise的原型對(duì)象上有3個(gè)實(shí)例方法:

Promise.prototype.then(onFulfilled, onRejected)

Promise.prototype.catch(onRejected)

Promise.prototype.finally(onFinally)

Promise.prototype.then(onFulfilled, onRejected):
then方法接收成功和失敗兩種情況的回調(diào)函數(shù)作為參數(shù),返回一個(gè)Promise對(duì)象。

參數(shù):onFulfilledonRejected回調(diào)函數(shù)。
onFulfilled:當(dāng) promise 對(duì)象變成 fulfilled 狀態(tài)時(shí)被調(diào)用。onFulfilled函數(shù)有一個(gè)參數(shù),即 promise 對(duì)象完成時(shí)的 value 值。如果onFulfilled不是函數(shù),它會(huì)在then方法內(nèi)部被替換成一個(gè)Identity函數(shù),即 (x) => (x) 。
onRejected:當(dāng) promise 對(duì)象變成 rejected 狀態(tài)時(shí)被調(diào)用。onRejected函數(shù)有一個(gè)參數(shù),即 promise 對(duì)象失敗時(shí)的 reason 值。如果onRejected不是函數(shù),它會(huì)在then方法內(nèi)部被替換成一個(gè)Thrower函數(shù),即 (reason) => {throw reason} 。

返回:一旦調(diào)用then方法的 promise 對(duì)象被完成或拒絕,將異步調(diào)用相應(yīng)的處理函數(shù)(onFulfilledonRejected),即將處理函數(shù)加入microtask隊(duì)列中。如果onFulfilledonRejected回調(diào)函數(shù):

返回一個(gè)值,則then返回的 promise 對(duì)象的status變?yōu)?b>fulfilled,value變?yōu)榛卣{(diào)函數(shù)的返回值;

不返回任何內(nèi)容,則then返回的 promise 對(duì)象的status變?yōu)?b>fulfilled,value變?yōu)?b>undefined;

拋出一個(gè)錯(cuò)誤,則then返回的 promise 對(duì)象的status變?yōu)?b>rejected,reason變?yōu)榛卣{(diào)函數(shù)拋出的錯(cuò)誤;

返回一個(gè)狀態(tài)為fulfilled的 promise 對(duì)象,則then返回的 promise 對(duì)象的status變?yōu)?b>fulfilled,value等于回調(diào)函數(shù)返回的 promise 對(duì)象的value值;

返回一個(gè)狀態(tài)為rejected的 promise 對(duì)象,則then返回的 promise 對(duì)象的status變?yōu)?b>rejected,reason等于回調(diào)函數(shù)返回的 promise 對(duì)象的reason值;

返回一個(gè)狀態(tài)為pending的 promise 對(duì)象,則then返回的 promise 對(duì)象的status變?yōu)?b>pending,且其status將隨著回調(diào)函數(shù)返回的 promise 對(duì)象的status變化而變化,之后其valuereason值也會(huì)和此 promise 對(duì)象的valuereason值相同。

這里提一下,這個(gè)地方看 MDN 文檔中文翻譯實(shí)在看不懂,之后看英文原文反而稍微理解了,希望之后在實(shí)現(xiàn) Promise 的過程中能理解更深。

    var fromCallback;
    
    var fromThen = Promise.resolve("done")
    .then(function() {
        fromCallback = new Promise(function(){});
        return fromCallback;
    });
    
    setTimeout(function() {
        console.log(fromCallback);    //fromCallback.status === "pending"
        console.log(fromThen);        //fromThen.status === "pending"
        console.log(fromCallback === fromThen);    //false
    }, 0);

Promise.prototype.catch(onRejected):
catch方法接收失敗情況的回調(diào)函數(shù)作為參數(shù),返回一個(gè)Promise對(duì)象。
參數(shù):onRejected回調(diào)函數(shù),表現(xiàn)同then中的onRejected參數(shù)。
返回:promiseObj.catch(onRejected) 與 promiseObj.then(undefined, onRejected) 返回值相同。

    Promise.resolve()
      .then( () => {
        // 返回一個(gè) rejected promise
        throw "Oh no!";
      })
      .catch( reason => {
        console.error( "onRejected function called: ", reason );
      })
      .then( () => {
        console.log( "I am always called even if the prior then"s promise rejects" );
      });

Promise.prototype.finally(onFinally):
finally方法接收onFinally回調(diào)函數(shù)作為參數(shù),返回一個(gè)Promise對(duì)象。
如果你想在 promise 執(zhí)行完畢后,無論其結(jié)果是成功還是失敗,都做一些相同的處理時(shí),可以使用finally方法。
參數(shù):onFinally回調(diào)函數(shù)
onFinally不接收任何參數(shù),當(dāng) promise 對(duì)象變成 settled (fulfilled / rejected) 狀態(tài)時(shí)onFinally被調(diào)用。
返回:如果onFinally回調(diào)函數(shù)

不返回任何內(nèi)容或者返回一個(gè)值或者返回一個(gè)狀態(tài)為fulfilled的 promise 對(duì)象,則finally返回的 promise 對(duì)象的statusvaluereason值與調(diào)用這個(gè)finally方法的 promise 對(duì)象的值相同;

拋出一個(gè)錯(cuò)誤或者返回一個(gè)狀態(tài)為rejected的 promise 對(duì)象,則finally返回的 promise 對(duì)象的status值變?yōu)?b>rejected,reason值變?yōu)楸粧伋龅腻e(cuò)誤或者回調(diào)函數(shù)返回的 promise 對(duì)象的reason值;

返回一個(gè)狀態(tài)為pending的 promise 對(duì)象,則finally返回的 promise 對(duì)象的status值變?yōu)?b>pending,且其status值將隨著回調(diào)函數(shù)返回的 promise 對(duì)象的status值變化而變化,之后其valuereason值也會(huì)和此 promise 對(duì)象的valuereason值相同。

Promise.reject("是我,開心嗎").finally(function() {
    var pro = new Promise(function(r){r("你得不到我")});    //pro.status === "fulfilled"
    return pro;    //`onFinally`回調(diào)函數(shù)返回一個(gè)狀態(tài)為`fulfilled`的 promise 對(duì)象
}).catch(function(reason) {
    console.log(reason);
});
結(jié)語(yǔ)

將 MDN 文檔整理了一下,加入了一些自己的理解,也花費(fèi)了一天的時(shí)間。現(xiàn)在Promise各個(gè)方法的參數(shù)、返回值、功能和使用方法已經(jīng)有個(gè)大概的了解了,為了進(jìn)一步理解其原理,接下來我打算簡(jiǎn)單地實(shí)現(xiàn)一下它。

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

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

相關(guān)文章

  • Promise——閱讀文檔簡(jiǎn)單實(shí)現(xiàn)(二)

    摘要:在和方法執(zhí)行的時(shí)候訂閱事件,將自己的回調(diào)函數(shù)綁定到事件上,屬性是發(fā)布者,一旦它的值發(fā)生改變就發(fā)布事件,執(zhí)行回調(diào)函數(shù)。實(shí)現(xiàn)和方法的回調(diào)函數(shù)都是,當(dāng)滿足條件對(duì)象狀態(tài)改變時(shí),這些回調(diào)會(huì)被放入隊(duì)列。所以我需要在某個(gè)變?yōu)闀r(shí),刪除它們綁定的回調(diào)函數(shù)。 前言 按照文檔說明簡(jiǎn)單地實(shí)現(xiàn) ES6 Promise的各個(gè)方法并不難,但是Promise的一些特殊需求實(shí)現(xiàn)起來并不簡(jiǎn)單,我首先提出一些不好實(shí)現(xiàn)或者容...

    dinfer 評(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
  • 理解 Javascript 中的 Promise

    摘要:理解承諾有兩個(gè)部分。如果異步操作成功,則通過的創(chuàng)建者調(diào)用函數(shù)返回預(yù)期結(jié)果,同樣,如果出現(xiàn)意外錯(cuò)誤,則通過調(diào)用函數(shù)傳遞錯(cuò)誤具體信息。這將與理解對(duì)象密切相關(guān)。這個(gè)函數(shù)將創(chuàng)建一個(gè),該將在到秒之間的隨機(jī)數(shù)秒后執(zhí)行或。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! showImg(https://segmentfault.com/img/bVbkNvF?w=1280&h=...

    paulli3 評(píng)論0 收藏0
  • 理解 Javascript 中的 Promise

    摘要:理解承諾有兩個(gè)部分。如果異步操作成功,則通過的創(chuàng)建者調(diào)用函數(shù)返回預(yù)期結(jié)果,同樣,如果出現(xiàn)意外錯(cuò)誤,則通過調(diào)用函數(shù)傳遞錯(cuò)誤具體信息。這將與理解對(duì)象密切相關(guān)。這個(gè)函數(shù)將創(chuàng)建一個(gè),該將在到秒之間的隨機(jī)數(shù)秒后執(zhí)行或。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! showImg(https://segmentfault.com/img/bVbkNvF?w=1280&h=...

    chaos_G 評(píng)論0 收藏0
  • Node程序debug小記

    摘要:當(dāng)前的部分代碼狀態(tài)超時(shí)再縮小了范圍以后,進(jìn)一步進(jìn)行排查。函數(shù)是一個(gè)很簡(jiǎn)單的一次性函數(shù),在第一次被觸發(fā)時(shí)調(diào)用函數(shù)。因?yàn)樯鲜鍪褂玫氖牵?,所以在獲取的時(shí)候,肯定為空,那么這就意味著會(huì)繼續(xù)調(diào)用函數(shù)。 有時(shí)候,所見并不是所得,有些包,你需要去翻他的源碼才知道為什么會(huì)這樣。 背景 今天調(diào)試一個(gè)程序,用到了一個(gè)很久之前的NPM包,名為formstream,用來將form表單數(shù)據(jù)轉(zhuǎn)換為流的形式進(jìn)行...

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

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

0條評(píng)論

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