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

資訊專欄INFORMATION COLUMN

es6 - Promise

wemallshop / 2553人閱讀

摘要:所謂異步編程中的異步是相對(duì)于同步的概念的。是一系列異步編程規(guī)范的統(tǒng)稱。如果中的回調(diào)函數(shù)返回一個(gè)值,那么返回的將會(huì)成為接受狀態(tài),并且將返回的值作為接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值。參考介紹基礎(chǔ)篇深入理解與異步編程。

es6 promise與異步編程

對(duì)于一些還不具備大量編程經(jīng)驗(yàn)的朋友來(lái)說(shuō),promise可能是es6比較難以掌握的點(diǎn)。首先是很多名詞,比如Promises,es6 Promise, 回調(diào)函數(shù)(callback),Promise/A+,異步編程等。下面就首先介紹下這些名詞的含義和區(qū)別。

所謂異步編程中的異步是相對(duì)于同步的概念的。js是單線程的語(yǔ)言,同一時(shí)間只能做一件事,為了指定一些稍后要執(zhí)行的代碼,我們需要異步。在客戶端,主要的異步方式有事件,setTimeout,Ajax等。Node的發(fā)展大大擴(kuò)展了js語(yǔ)言的邊界,我們知道,Node使用非阻塞IO模型,它使用回調(diào)函數(shù)模式來(lái)實(shí)現(xiàn)異步編程。比如:

readFile("example.txt", function(err, contents){
    if(err){ throw err; }
    console.log(contents);
});
console.log("Hi!");

上面代碼中readFile的第二個(gè)參數(shù)就是回調(diào)函數(shù)。它會(huì)在讀取完example.txt后被添加到執(zhí)行隊(duì)列中。上面代碼的執(zhí)行順序是--執(zhí)行readFile函數(shù),在遇到讀取文件時(shí)暫停,打印"Hi",讀取文件結(jié)束后將回調(diào)添加到作業(yè)隊(duì)列中,執(zhí)行回調(diào)函數(shù),打印contents。

本來(lái)呢,使用回調(diào)函數(shù)是能夠完成異步編程的。但是隨著代碼的邏輯越復(fù)雜,這種異步編程方式越來(lái)越難以閱讀和追蹤程序錯(cuò)誤,所以發(fā)展出了Promises規(guī)范來(lái)完成異步編程。

Promises是一系列異步編程規(guī)范的統(tǒng)稱。我們需要了解的是其中的Promise/A+規(guī)范。es6通過(guò)Promise這個(gè)內(nèi)建對(duì)象實(shí)現(xiàn)了該規(guī)范。所以我們可以使用es6中的Promise對(duì)象來(lái)進(jìn)行異步編程。

下面將對(duì)es6中的Promise對(duì)象進(jìn)行介紹。至于jQuery中延遲對(duì)象$.deferred(),根據(jù)規(guī)范自己實(shí)現(xiàn)promise和ES7的Async/Await異步方式等更多內(nèi)容,后面會(huì)專門寫一篇文章進(jìn)行介紹。

語(yǔ)法 Promise的3種狀態(tài)

一個(gè)promise實(shí)例有3種狀態(tài),分別是:

pending -- 掛起,表示Promise結(jié)果還未知。

fulfilled -- 已完成, 表示Promise成功完成。

rejected -- 已拒絕,表示Promise未成功結(jié)束。

promise處于這3種狀態(tài)中的一種,并且可以由pending狀態(tài)變?yōu)閒ulfilled狀態(tài),或由pending變?yōu)閞ejected狀態(tài)。反之則不行。

為了便于理解,下面將通過(guò)一個(gè)生活化的例子,來(lái)解釋什么是Promise?

Promise是允諾的意思。它就是一個(gè)關(guān)于未發(fā)生的事情的承諾。比如:

你訂了一份燒烤,店家說(shuō)半個(gè)小時(shí)內(nèi)送到,這就是一個(gè)Promise?,F(xiàn)在,這個(gè)Promise還沒(méi)有發(fā)生,所以可能半個(gè)小時(shí)內(nèi)配送成功或者失敗。對(duì)此,你預(yù)備了兩種處理方式:成功 -- 美滋滋的吃燒烤,失敗 -- 去樓下店里吃。

在半個(gè)小時(shí)內(nèi),這個(gè)Promise處于pending狀態(tài),你正常上網(wǎng),擼代碼。一段時(shí)間后,這個(gè)promise就有了結(jié)果。是成功(fulfilled)或者失敗(rejected)。根據(jù)這個(gè)結(jié)果,你之前的兩種處理方式就會(huì)相應(yīng)執(zhí)行。這就是promise。

對(duì)應(yīng)的代碼如下:

let promise = new Promise(function(resolve, reject){
    //等待店家送來(lái)中...
    let result = "配送成功"? true : false;
    if(result){
        resolve(value);
    }else{
        reject(reason);
    }
});

promise.then(function(value){
    //美滋滋吃燒烤...
    //value為上面resolve()中傳遞的值, 比如共100塊錢。
}, function(reason){
    //叫上隔壁老王去樓下吃...
    //reason為上面reject()的傳遞的原因,比如烤糊了...
});

上面代碼就是通過(guò)promise異步編程的代碼。這里要注意的是Promise構(gòu)造函數(shù)接收一個(gè)函數(shù)作為參數(shù),函數(shù)內(nèi)部是異步的邏輯。這個(gè)函數(shù)接收兩個(gè)參數(shù):resolve和reject。resolve()可以把promise推向fulfilled狀態(tài),reject()可以把promise推向rejected狀態(tài)。

promise有個(gè)then方法,用于處理promise成功或失敗后的邏輯。then有兩個(gè)參數(shù):
參數(shù)1為promise成功時(shí)執(zhí)行的函數(shù),該函數(shù)的參數(shù)value對(duì)應(yīng)于上面resolve(value)中的value值;
參數(shù)2為promise失敗時(shí)執(zhí)行的函數(shù),該函數(shù)的參數(shù)reason對(duì)應(yīng)于reject(reason)中的reason值,表示失敗的原因。
一旦promise有了結(jié)果(成功或失敗),就會(huì)執(zhí)行對(duì)應(yīng)then中的函數(shù)。

通過(guò)Promise處理Ajax的例子

Ajax是客戶端最常用的異步編程場(chǎng)景,下面一個(gè)例子演示了使用Promise進(jìn)行Ajax操作的代碼。

function getData(method, url){
  let promise = new Promise(function(resolve, reject){
    let xmlHttp = new XMLHttpRequest();
    xmlHttp.open(method, url);
    xmlHttp.send();
    xmlHttp.onload = function () {
      if (this.status == 200 ) {
        resolve(this.response);
      } else {
        reject(this.statusText);
      }
    };
    xmlHttp.onerror = function () {
      reject(this.statusText);
    };
  })
  return promise;
}

getData("get","www.xxx.com").then(successFun, failFun);

function successFun(value){
  //Ajax成功處理函數(shù)...
}
function failFun(reason){
  //Ajax失敗處理函數(shù)...
}
創(chuàng)建一個(gè)已決的Promise

前面的例子promise創(chuàng)建時(shí),promise都處于pending狀態(tài),根據(jù)異步操作的結(jié)果將promise推向成功或失敗狀態(tài)。

Promise類型有兩個(gè)靜態(tài)方法Promise.resolve(value),Promise.reject(reason)可以分別創(chuàng)建已經(jīng)是fulfilled和已經(jīng)是rejected狀態(tài)的promise。
比如:

let promise = Promise.resolve(44);
promise.then(function(value){
  console.log("fulfilled", value);
})

上面代碼promise在被創(chuàng)建出來(lái)時(shí),已經(jīng)是fulfilled狀態(tài),接下來(lái)會(huì)直接將then中的回調(diào)函數(shù)加入到作業(yè)隊(duì)列中,等待作業(yè)隊(duì)列中前面的任務(wù)完成后執(zhí)行該函數(shù)。

這里傳入Promise.resolve(value)和Promise.reject(reason)中的參數(shù)和之前Promise構(gòu)造是對(duì)應(yīng)的參數(shù)是一樣的。

Promise.prototype.then()和Promise.prototype.catch()

上面已經(jīng)演示過(guò)promise實(shí)例上then方法的用法,每一個(gè)promise實(shí)例還具有catch方法。

catch()方法只處理reject的情況,他的行為與調(diào)用Promise.prototype.then(undefined, onRejected)相同。比如:

let p = new Promise(function(resolve, reject){
    //...
    reject(new Error("something wrong!"))
})
p.catch(function(reason){
    //拒絕
})

上面catch方法中的回調(diào)在promise被reject時(shí)調(diào)用。

then()和catch()的返回值

每次對(duì)then()或catch()的調(diào)用都會(huì)返回另一個(gè)promise,這也是很多代碼可以寫成類似鏈?zhǔn)秸{(diào)用的原因。比如:

let p1 = new Promise(function(resolve, reject){
  resolve(42);
});
let p2 = p1.then(function(value){
  console.log(value);
})

p2.then(function(){
  console.log("Finished");
}, function(){
    console.log("something wrong!");
});

p1 == p2 // false,注意:p1.then()會(huì)返回一個(gè)新的promise,所以p1與p2并不相等

//可以寫成鏈?zhǔn)秸{(diào)用的形式,比如
p1.then(function(value){
  console.log(value)
}).then(function(){
  console.log("do something");
}).then(function(){
  console.log("Finished");
})

在上面代碼中,p1.then()返回了一個(gè)promise為p2, 那么p2的狀態(tài)和p1之間有什么關(guān)系呢?

更具體一點(diǎn)說(shuō),當(dāng)p1變?yōu)閒ulfilled時(shí),p1.then()返回的p2是什么狀態(tài)呢?二者有什么聯(lián)系呢?

p2的行為與p1.then()中回調(diào)函數(shù)的返回值有關(guān):

如果then中的回調(diào)函數(shù)拋出一個(gè)錯(cuò)誤,或者回調(diào)函數(shù)中調(diào)用reject(reason),那么then返回的Promise將會(huì)成為拒絕狀態(tài),并且將拋出的錯(cuò)誤作為拒絕狀態(tài)的回調(diào)函數(shù)的參數(shù)值。

如果then中的回調(diào)函數(shù)返回一個(gè)值,那么then返回的Promise將會(huì)成為接受狀態(tài),并且將返回的值作為接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值。

如果then中的回調(diào)函數(shù)返回一個(gè)已經(jīng)是接受狀態(tài)的Promise,那么then返回的Promise也會(huì)成為接受狀態(tài),并且將那個(gè)Promise的接受狀態(tài)的回調(diào)函數(shù)的參數(shù)值作為該被返回的Promise的接受狀態(tài)回調(diào)函數(shù)的參數(shù)值。

如果then中的回調(diào)函數(shù)返回一個(gè)已經(jīng)是拒絕狀態(tài)的Promise,那么then返回的Promise也會(huì)成為拒絕狀態(tài),并且將那個(gè)Promise的拒絕狀態(tài)的回調(diào)函數(shù)的參數(shù)值作為該被返回的Promise的拒絕狀態(tài)回調(diào)函數(shù)的參數(shù)值。

如果then中的回調(diào)函數(shù)返回一個(gè)未定狀態(tài)(pending)的Promise,那么then返回Promise的狀態(tài)也是未定的,并且它的終態(tài)與那個(gè)Promise的終態(tài)相同;同時(shí),它變?yōu)榻K態(tài)時(shí)調(diào)用的回調(diào)函數(shù)參數(shù)與那個(gè)Promise變?yōu)榻K態(tài)時(shí)的回調(diào)函數(shù)的參數(shù)是相同的。

如果then中的回調(diào)函數(shù)無(wú)顯式的返回值,并且也沒(méi)有調(diào)用reject(),那么返回的Promise為接收狀態(tài)。

Promise.all()處理多個(gè)promise

Promise內(nèi)建對(duì)象上的靜態(tài)方法Promise.all()用于處理多個(gè)promise的情況。

Promise.all([promise1, promise2,...])返回一個(gè)promise的實(shí)例,接收一個(gè)promise組成的數(shù)組為參數(shù)。只有當(dāng)數(shù)組內(nèi)的promise都成功時(shí),才會(huì)調(diào)用對(duì)應(yīng)的then中的成功處理函數(shù),只要有一個(gè)不成功,那么調(diào)用對(duì)應(yīng)的拒絕處理函數(shù)。

依然使用前面那么訂燒烤的例子,你不僅訂了燒烤,還在另一家訂了啤酒。打算等到燒烤和啤酒都配送成功后一起吃,美滋滋~~。比如:

Promise.all([訂燒烤,訂啤酒]).then(function(value){
    //吃燒烤,喝啤酒...
}, function(reason){
    //拒絕的原因,烤糊了或者啤酒賣完了...
})

這里要注意的一點(diǎn)是,對(duì)于數(shù)組中的promise,只要有任一個(gè)promise為拒絕,那么就會(huì)立即執(zhí)行then中的拒絕處理函數(shù),并不會(huì)等待其他promise的結(jié)果。只有當(dāng)所有promise的結(jié)果都成功時(shí),才執(zhí)行then中的成功處理函數(shù)。比如:

var p1 = new Promise(function(resolve, reject){
  setTimeout(function(){
    console.log("A");
    resolve();
  }, 1000)
});
var p2 = Promise.reject(new Error("error"));
var p3 = new Promise(function(resolve, reject){
  setTimeout(function(){
    console.log("B");
    resolve();
  }, 0)
});
Promise.all([p1,p2,p3]).then(function(value){
  console.log("success!");
}, function(reason){
  console.log("failed");
})
//結(jié)果為failed B  A

由于p2為已拒絕狀態(tài)的promise,所以Promise.all()立即變?yōu)榫芙^狀態(tài),打印failed,p1和p2會(huì)繼續(xù)執(zhí)行,但對(duì)于Promise.all()的結(jié)果沒(méi)有影響。

Promise.race()處理多個(gè)promise

Promise內(nèi)建對(duì)象上的靜態(tài)方法Promise.race()同樣用于處理多個(gè)promise的情況。同樣返回一個(gè)Promise,同樣接收一個(gè)promise數(shù)組作為參數(shù)。

與all不同的地方在于,數(shù)組中的promise就像在賽跑一樣(race),并且只關(guān)心第一名的情況,只要有其中一個(gè)promise有了結(jié)果,Promise.race()的狀態(tài)就會(huì)立即與該promise相同。
數(shù)組中其他promise繼續(xù)執(zhí)行,但對(duì)于Promise.race()的結(jié)果沒(méi)有影響。

注意事項(xiàng)

我們構(gòu)造promise實(shí)例的代碼是立即執(zhí)行的,而then方法中的回調(diào)函數(shù)是異步調(diào)用的,在promise的狀態(tài)變?yōu)槌晒蚓芙^時(shí),才會(huì)把相應(yīng)的處理函數(shù)添加到promise工作隊(duì)列中。并且該函數(shù)會(huì)先于setTimeout執(zhí)行。例如:

var promise = new Promise(function(resolve, reject){
  console.log("A");
  resolve("C");
})

console.log("B");

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

promise.then(function(value){
  console.log(value)
});
//打印A, B, C, D

如果then方法中傳入的參數(shù)被忽略,或者是非函數(shù),比如:

p.then(function(value){
    //...
})
//或者
p.then(undefined, function(reason){
    //...
})

那么,相應(yīng)的回調(diào)處理函數(shù)被忽略,then方法返回的promise會(huì)保留上一個(gè)promise的狀態(tài)和參數(shù)。最典型的例子:

var p = new Promise(function(resolve, reject){
    reject(new Error("error"));
})
p.then(function(value){
    //...
}).then(function(value){
    //...
}).then(undefined, function(reason){
    console.log(reason);
})
//打印"error"

p的前兩次then調(diào)用的拒絕處理函數(shù)被忽略,然后reject狀態(tài)和錯(cuò)誤信息就一直往后傳遞,直到被最后一次then調(diào)用捕獲。

最佳實(shí)踐

關(guān)于Promise的知識(shí)點(diǎn)很多,但是最常用的場(chǎng)景就是Ajax。比如:

function getData(method, url){
  var promise = new Promise(function(resolve, reject){
    //Ajax獲取數(shù)據(jù)的代碼...
    if(success){
      resolve(response)
    }else{
      reject(statusText)
    }
  })
  return promise;
}

getData("get","www.xxx.com").then(Fun1).then(Fun2).then(Fun3).catch(function(reason){
  //錯(cuò)誤處理邏輯...
});

更多關(guān)于es6的內(nèi)容,可以關(guān)注右側(cè)我的專欄--學(xué)習(xí)ES6。

參考:
MDN Javascript Promise.
Promise介紹-基礎(chǔ)篇.
《深入理解ES6》-- Promise與異步編程。

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

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

相關(guān)文章

  • ES6-7

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

    mudiyouyou 評(píng)論0 收藏0
  • 通過(guò) ES6 Promise 和 jQuery Deferred 的異同學(xué)習(xí) Promise

    摘要:和和都有和,但是略有不同。實(shí)際上返回的是一個(gè)對(duì)象。和添加的回調(diào),添加的回調(diào)。所以在調(diào)用成功的情況下執(zhí)行添加的回調(diào),調(diào)用失敗時(shí)執(zhí)行添加的回調(diào)。,產(chǎn)生對(duì)象并,產(chǎn)生對(duì)象并,然后繼續(xù)處理,的語(yǔ)法糖,和的差不多但不同。 Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過(guò)它們的作用可以簡(jiǎn)單的用兩句話來(lái)描述 Deffere...

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

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

    tuniutech 評(píng)論0 收藏0
  • 淺談ES6原生Promise

    摘要:如果有錯(cuò)誤,則到的第二個(gè)回調(diào)函數(shù)中,對(duì)錯(cuò)誤進(jìn)行處理。假設(shè)第一個(gè)的第一個(gè)回調(diào)沒(méi)有返回一個(gè)對(duì)象,那么第二個(gè)的調(diào)用者還是原來(lái)的對(duì)象,只不過(guò)其的值變成了第一個(gè)中第一個(gè)回調(diào)函數(shù)的返回值。 ES6標(biāo)準(zhǔn)出爐之前,一個(gè)幽靈,回調(diào)的幽靈,游蕩在JavaScript世界。 正所謂: 世界本沒(méi)有回調(diào),寫的人多了,也就有了})})})})})。 Promise的興起,是因?yàn)楫惒椒椒ㄕ{(diào)用中,往往會(huì)出現(xiàn)回調(diào)函數(shù)一...

    yedf 評(píng)論0 收藏0
  • ES6Promise:要優(yōu)雅,也要浪漫

    摘要:就算改變已經(jīng)發(fā)生了,即使再對(duì)對(duì)象添加回調(diào)函數(shù),也會(huì)立即得到這個(gè)結(jié)果。方法接收個(gè)參數(shù),第一個(gè)參數(shù)是狀態(tài)的回調(diào)函數(shù),第二個(gè)參數(shù)可選是狀態(tài)的回調(diào)函數(shù)。簡(jiǎn)單來(lái)講,就是能把原來(lái)的回調(diào)寫法分離出來(lái),在異步操作執(zhí)行完后,用鏈?zhǔn)秸{(diào)用的方式執(zhí)行回調(diào)函數(shù)。 在ECMAScript 6標(biāo)準(zhǔn)中,Promise被正式列為規(guī)范,Promise,字面意思就是許諾,承諾,嘿,聽(tīng)著是不是很浪漫的說(shuō)?我們來(lái)探究一下這個(gè)浪...

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

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

0條評(píng)論

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