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

資訊專欄INFORMATION COLUMN

只為那句承諾-大話Promise

EastWoodYang / 2392人閱讀

摘要:什么是是異步編程的一種解決方案,比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大。函數(shù)可以將狀態(tài)轉(zhuǎn)變?yōu)闋顟B(tài)。對(duì)象通過(guò)方法來(lái)添加回調(diào)函數(shù)。當(dāng)發(fā)生錯(cuò)誤的時(shí)候可以通過(guò)方法,來(lái)定義回調(diào)函數(shù)。接受數(shù)組作為參數(shù)傳入,每個(gè)元素都是一個(gè)對(duì)象。

大家周末好,要說(shuō)最近幾年什么語(yǔ)言大紅大紫,當(dāng)屬JavaScript了。話說(shuō)雖然是10天就創(chuàng)造出的語(yǔ)言,但是人家能文能武。web前端自然不必多說(shuō)了,各種框架你方登罷我上場(chǎng),前兩年還是Angular一統(tǒng)天下,這兩年React又是大紅大紫,還有Vue最近異軍突起,好不紅火。要是僅僅是前端也就算了,但是由于Node.js人家在后臺(tái)也能寫(xiě),React Native的出現(xiàn)讓人家移動(dòng)端也能做。好吧,還有硬件上也出現(xiàn)Ruff方案,好像硬件上也能寫(xiě)了。真是讓人感覺(jué)挺有意思的事情。

圖表君上邊叨叨了這么多,難道是為JavaScript唱贊歌的嗎?呵呵,其實(shí)并不是。只是最近因?yàn)樵谟蒙掀恼陆榻B的AWS Lambda。Lambda現(xiàn)在只支持Java,Node.js,Python。最終選擇了Node.js進(jìn)行開(kāi)發(fā),不可避免的要牽扯到異步操作的問(wèn)題。那么今天就來(lái)聊聊JavaScript中的Promise。

什么是Promise

Promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。

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

上面是Promise的一個(gè)定義,引自阮一峰的ES6標(biāo)準(zhǔn)入門(mén)一書(shū)。S6標(biāo)準(zhǔn)入門(mén)。多說(shuō)一句,目前的JavaScript項(xiàng)目無(wú)論是前臺(tái)或者是后臺(tái),都應(yīng)該采用ES6的標(biāo)準(zhǔn)語(yǔ)法來(lái)寫(xiě),ES6讓JavaScript的書(shū)寫(xiě)更加的清晰和規(guī)范。

基本用法

如何來(lái)構(gòu)造一個(gè)promise對(duì)象呢?ES6中提供了原生Promise可以使用。

var promise = new Promise(function(resolve, reject) {
  // ... here is some code

  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

上面的例子給出了new一個(gè)promise對(duì)象的方法,Promise的構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù)傳入,這個(gè)函數(shù)的兩個(gè)參數(shù),reject和resolve是JavaScript本身提供的兩個(gè)函數(shù)。
一個(gè)promise對(duì)象有三個(gè)狀態(tài)分別是,pending,resolved,rejected。resolve函數(shù)可以將pending狀態(tài)轉(zhuǎn)變?yōu)閞esolved狀態(tài)。reject函數(shù)可以講pending狀態(tài)轉(zhuǎn)變了rejected狀態(tài)。對(duì)象的狀態(tài)不受外界的影響,同樣也是promise名字的由來(lái)。外部你拿著我的一個(gè)承諾,一會(huì)我會(huì)告訴你我的狀態(tài)。

promise對(duì)象通過(guò)then方法來(lái)添加回調(diào)函數(shù)。例如這樣

promise.then(data=> console.log(data), err=> console.log(err));

當(dāng)promise被resolved的時(shí)候,就會(huì)把data log出來(lái)。當(dāng)promise被rejected的時(shí)候,err就會(huì)被log出來(lái)。
看上去好像是挺簡(jiǎn)單的,的確Promise的應(yīng)用使得異步的操作,以同步的形式表現(xiàn)出來(lái)。當(dāng)發(fā)生錯(cuò)誤的時(shí)候可以通過(guò)catch方法,來(lái)定義回調(diào)函數(shù)。

怎么用

上邊都是一些干巴巴的定義,那么到底該怎么用呢?Promise又怎么樣的解決了問(wèn)題呢,下邊我們看一個(gè)例子。假設(shè)下邊一個(gè)場(chǎng)景,我們一個(gè)服務(wù),從一個(gè)外邊service獲取數(shù)據(jù),然后寫(xiě)到一個(gè)db里,或者一個(gè)存儲(chǔ)里,最后在把存儲(chǔ)的狀態(tài)龍出來(lái),那么如果沒(méi)有promise是怎么寫(xiě)的呢?可能會(huì)是這樣。

getData(function (value1) {
  storeToDb(value1, function(value2) {
    logStore(value2, function(value3) {
      //...
    });
  });
});

傳統(tǒng)的回調(diào)的寫(xiě)法,這樣使得代碼邏輯混亂在一起。再想想如果再加上錯(cuò)誤處理的情況,更是酸爽。那么用promise來(lái)寫(xiě)會(huì)怎么樣呢?看下邊這樣的代碼

function getData(){
    return new Promise((resolve,reject) =>{
        // ... send request to get data
        
        if(/* get successfully*/){
            resolve(data)
        }else{
            reject(err)
        }
    })
}

function storeData(data){
    return new Promise((resolve,reject)=>{
        // ... store the data
        
        if(/*store successfully*/){
            resolve(data)
        }else{
            reject(err)
        }
    })
}


getData()
    .then(data => storeData(data))
    .then(data => console.log("the process is done",data));
    .catch(err => console.error("there is the err",err));

這樣寫(xiě)是不是就是很清楚了,先getData,然后再storeData,最后將這次運(yùn)行的情況log了出來(lái),其中有任何的問(wèn)題,在catch中都可以Catch出來(lái)。代碼的邏輯以同步的方式得到了體現(xiàn)。我們來(lái)看看如果是其他語(yǔ)言會(huì)怎么寫(xiě),下邊是個(gè)ruby的語(yǔ)言的例子

def get_data 
    // ...send request
    
    if /*get successfully */
        return data
    else
        raise GetDataError
    end
end


def store_data
    // ...save to db
    
    if /*save successfully */
        return data
    else
        raise StoreDataError
    end
end


/*Main Logic*/
begin
    request_data = get_data
    db_data = store_data request_data
    p "here is the store data #{db_data}"
rescue e
    p "here is some errors #{e}"
end

我們對(duì)比兩個(gè)例子,可以看到在使用的Promise后讓JavaScript的異步方式的編程模式更將清楚,也更加讓人容易理解。

由于JavaScript的執(zhí)行環(huán)境是單線程的,所以大量采用了異步的方式來(lái)進(jìn)行編程,這使得我們寫(xiě)起代碼并不十分符合我們一般的習(xí)慣。但是Promise的出現(xiàn)讓這種問(wèn)題能得到一定程度的緩解。

但是異步操作異步操作的好處,比如上邊的那個(gè)例子,如果我們想要做的同時(shí)并發(fā)10個(gè)操作,那個(gè)在ruby或者其他語(yǔ)言中中就要啟多個(gè)線程來(lái)進(jìn)行。但是JavaScript就完全沒(méi)有這個(gè)問(wèn)題。只要簡(jiǎn)單的loop下就行了。

但是如果我們想要在這10個(gè)操作完成后根據(jù)返回的狀態(tài)做點(diǎn)其他操作該怎么做呢?這時(shí)候用Promise.all就是最好的了。

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

Promise.all接受數(shù)組作為參數(shù)傳入,每個(gè)元素都是一個(gè)promise對(duì)象。只要所有子promise都resolved以后,p才會(huì)被resolved。只要有一個(gè)被rejected,這個(gè)p就會(huì)被rejected。但是有一點(diǎn)是這些子promise之間并不會(huì)有順序的關(guān)系。再來(lái)看一個(gè)例子:

var guid = 0;
function run() {
  guid++;
  var id = guid;
  return new Promise(resolve => {
    setTimeout(function () {
      console.log(id);
      resolve(id);
    }, (Math.random() * 1.5 | 0) * 1000);
  });
}

var promises = Array.from({ length: 10 }, run);
Promise.all(promises)

OUTPUT:

2
3
5
6
7
8
10
1
4
9

從這次的output可以看到,promise之間并沒(méi)有順序執(zhí)行,實(shí)際上是并發(fā)的。那么如何讓這些promise是順序執(zhí)行呢?留個(gè)大家自己思考下,下篇文章,我們揭曉?;蛘呖梢月?lián)系圖表君,私下告訴你答案哦。
ps,當(dāng)然也可以用一些第三方的庫(kù)和方案,例如(async)來(lái)實(shí)現(xiàn)順序操作,但是代碼的樂(lè)趣不就是做些思維挑戰(zhàn)嗎:)

原創(chuàng)文章,歡迎轉(zhuǎn)發(fā),但請(qǐng)標(biāo)明出處。歡迎關(guān)注圖表君的公眾號(hào),一起成長(zhǎng)。在微信中搜索 “多彩數(shù)據(jù)” 或者 “Data_Visualization”

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

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

相關(guān)文章

  • 大話+圖說(shuō):Java字節(jié)碼指令——只為讓你懂

    摘要:有點(diǎn)基礎(chǔ)的人一定都知道,命令會(huì)將源文件編譯成字節(jié)碼文件,即文件,其中就包含了大量的字節(jié)碼指令。關(guān)于字節(jié)碼指令的分類,可以從兩個(gè)維度進(jìn)行一是指令的功能,二是指令操作的數(shù)據(jù)類型。 前言 隨著Java開(kāi)發(fā)技術(shù)不斷被推到新的高度,對(duì)于Java程序員來(lái)講越來(lái)越需要具備對(duì)更深入的基礎(chǔ)性技術(shù)的理解,比如Java字節(jié)碼指令。不然,可能很難深入理解一些時(shí)下的新框架、新技術(shù),盲目一味追新也會(huì)越來(lái)越感乏力。...

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

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

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

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

    chaos_G 評(píng)論0 收藏0
  • 大話javascript 4期:事件循環(huán)(2)

    摘要:只要指定過(guò)回調(diào)函數(shù),這些事件發(fā)生時(shí)就會(huì)進(jìn)入任務(wù)隊(duì)列,等待主線程讀取。三主線程從任務(wù)隊(duì)列中讀取事件,這個(gè)過(guò)程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為事件循環(huán)。 一、任務(wù)隊(duì)列 同步任務(wù)與異步任務(wù)的由來(lái) 單線程就意味著,所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。如果前一個(gè)任務(wù)耗時(shí)很長(zhǎng),后一個(gè)任務(wù)就不得不一直等著。 如果排隊(duì)是因?yàn)橛?jì)算量大,CPU忙不過(guò)來(lái),倒也算了,但是很多時(shí)候C...

    李昌杰 評(píng)論0 收藏0
  • ES6的Promise:要優(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)寫(xiě)法分離出來(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元查看
<