Promise贰军、generator、async類同步編程

javascript語(yǔ)言特性的影響,編程過(guò)程中充斥著大量異步回調(diào)词疼,這會(huì)讓代碼維護(hù)起來(lái)特別麻煩俯树,一步步走向回調(diào)地獄。社區(qū)中最早提出Promise解決方案贰盗,es6將其融入語(yǔ)法標(biāo)準(zhǔn)许饿,并提供了generatorasync舵盈,向類同步編程不斷努力陋率。本文會(huì)通過(guò)這三個(gè)方面演示類同步進(jìn)化過(guò)程。

1.Promise

Promise提供異步編程的容器秽晚,包含異步代碼瓦糟,在得到異步結(jié)果時(shí),通過(guò)resolve傳遞數(shù)據(jù)(resove對(duì)應(yīng)then所指定的函數(shù)赴蝇,其實(shí)也就是單個(gè)過(guò)程的異步回調(diào)菩浙,可以理解成將之前的回調(diào)函數(shù)放在then方法中定義)。

以ajax請(qǐng)求封裝為例:
  • 傳統(tǒng)形式
function ajax(url, success) {
       var xhr = new XMLHttpRequest();
       xhr.open("GET", url);
       xhr.send();
       xhr.onreadystatechange = function () {
           if (xhr.status == 200 && xhr.readyState == 4) {
               //將請(qǐng)求結(jié)果作為實(shí)參傳入成功回調(diào)
               success(xhr.responseText);
           }
       }
   }
   //如果兩個(gè)異步過(guò)程有先后順序扯再,則會(huì)出現(xiàn)這種嵌套情況
   ajax("http://vebcoder.cn:9527/api/getTypeOne", function (res) {
       console.log(res);
       ajax("http://vebcoder.cn:9527/api/goodList", function (res) {
           console.log(res);
       })
   })
  • Promise形式
function ajax(url) {
     //promise容器包裹異步過(guò)程
     return new Promise(resolve => {

        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.send();
        xhr.onreadystatechange = function () {
             if (xhr.status == 200 && xhr.readyState == 4) {
                 //將異步結(jié)果使用resolve進(jìn)行傳遞
                 resolve(xhr.responseText);
             }
        }

     })
}


ajax("http://vebcoder.cn:9527/api/getTypeOne")
.then(res=>{
    console.log(JSON.parse(res))
 })
.then(()=>{
    return ajax("http://vebcoder.cn:9527/api/goodList")
})
.then(res=>{
    console.log(JSON.parse(res))
})

解決了回調(diào)函數(shù)橫向發(fā)展的問(wèn)題芍耘,變成了縱向發(fā)展結(jié)構(gòu)。直觀確實(shí)很直觀但是一大堆的then方法熄阻,斋竞!接下來(lái)generator登場(chǎng)


2.generator

乍一看,generator不過(guò)是一個(gè)有多個(gè)返回值的函數(shù)而已秃殉,奧妙在于如果不調(diào)用next方法坝初,代碼會(huì)停止執(zhí)行的。

  • 基礎(chǔ)用法
//function后加*
function* Gen(){
     console.log(1);
     yield;
     console.log(2)
     yield;
     console.log(3);
     return;
}
//調(diào)用函數(shù)獲得指針對(duì)象
var g=Gen();
g.next();//1
g.next();//2
g.next();//3

第一次調(diào)用next執(zhí)行到第一個(gè)yield钾军,第三次執(zhí)行到函數(shù)末尾return的位置鳄袍。

  • 奧妙之處
function* Gen(){
    //用變量接收yield命令
    var res=yield;
    console.log(res)
}
var g=Gen();
g.next();
//next傳入?yún)?shù)
g.next(100);//100

第一次調(diào)用next方法,代碼執(zhí)行到yield停止執(zhí)行吏恭。第二次調(diào)用next傳入?yún)?shù)拗小,代碼繼續(xù)執(zhí)行,并將傳入next的參數(shù)賦值給res變量樱哼。next方法可以帶一個(gè)參數(shù)哀九,該參數(shù)就會(huì)被當(dāng)作上一個(gè)yield表達(dá)式的返回值。
那么我們就可以這樣做:

//上述封裝的ajax方法-傳統(tǒng)形式
function* Gen(){
                                                 //請(qǐng)求成功開始下一步
    ajax("http://vebcoder.cn:9527/api/getTypeOne",res=>{g.next(res)})
    // 接收yield返回值
    let res=yield;
    console.log(res)//請(qǐng)求的數(shù)據(jù)結(jié)果
}
var g=Gen();
// 開始執(zhí)行代碼
g.next();

//上述封裝的ajax方法-Promise形式
function* Gen(){
                                                    //請(qǐng)求成功開始下一步
    ajax("http://vebcoder.cn:9527/api/getTypeOne").then(res=>{g.next(res)})
    // 接收yield返回值
    let res=yield;
    console.log(res)//請(qǐng)求的數(shù)據(jù)結(jié)果
}
var g=Gen();
// 開始執(zhí)行代碼
g.next();

使用口訣:上一步回調(diào)搅幅,下一步阅束,接收yield等待結(jié)果傳入


按理說(shuō)這種形式已經(jīng)不錯(cuò)了,不用再往下看了茄唐,除非你能忍紫⒙恪!


3.async

asyncgenerator的語(yǔ)法糖,你只需關(guān)注兩部呼盆、步操作就行年扩。相當(dāng)于對(duì)Promisegenerator進(jìn)行了融合。

async function Asy(){
                                    //等待promise實(shí)例
    let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
    console.log(res)//請(qǐng)求的數(shù)據(jù)結(jié)果
}
Asy();

//結(jié)合自執(zhí)行函數(shù)
;(async function(){
    let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
    console.log(res)//請(qǐng)求的數(shù)據(jù)結(jié)果
}())

async函數(shù)就是將Generator 函數(shù)的星號(hào)(*)替換成async宿亡,將yield替換成await常遂。
注意:await后面需要跟一個(gè)promise實(shí)例,無(wú)需手動(dòng)傳遞結(jié)果挽荠!

最后來(lái)一個(gè)對(duì)比(有次序的異步過(guò)程):

//傳統(tǒng)方式(對(duì)應(yīng)上述傳統(tǒng)ajax封裝形式)
ajax("http://vebcoder.cn:9527/api/getTypeOne", function (res) {
    console.log(res);
    ajax("http://vebcoder.cn:9527/api/goodList", function (res) {
        console.log(res);
    })
})

//promise (對(duì)應(yīng)上述promise ajax封裝形式)
ajax("http://vebcoder.cn:9527/api/getTypeOne")
    .then(res=>{
        console.log(JSON.parse(res))
    })
    .then(()=>{
        return ajax("http://vebcoder.cn:9527/api/goodList")
    })
    .then(res=>{
        console.log(JSON.parse(res))
    })

//generator (對(duì)應(yīng)上述promise ajax封裝形式)
function* Gen(){
                                                    //請(qǐng)求成功開始下一步
    ajax("http://vebcoder.cn:9527/api/getTypeOne").then(res=>{g.next(res)})
    // 接收yield返回值
    let res=yield;
    console.log(res);

    ajax("http://vebcoder.cn:9527/api/goodList").then(res=>{g.next(res)})
    // 接收yield返回值
    let res2=yield;
    console.log(res2);

}
var g=Gen();
// 開始執(zhí)行代碼
g.next();

//async (對(duì)應(yīng)上述promise ajax封裝形式)
// 發(fā)送請(qǐng)求
;(async function(){
    let res=await ajax("http://vebcoder.cn:9527/api/getTypeOne")
    console.log(res)//請(qǐng)求的數(shù)據(jù)結(jié)果
    let res2=await ajax("http://vebcoder.cn:9527/api/goodList")
    console.log(res2)//請(qǐng)求的數(shù)據(jù)結(jié)果
}())

async有更好的語(yǔ)義克胳,幾乎達(dá)到與同步代碼一樣的編程體驗(yàn)!

2019圈匆,不過(guò)是追求喜新厭舊的年頭漠另!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市跃赚,隨后出現(xiàn)的幾起案子笆搓,更是在濱河造成了極大的恐慌,老刑警劉巖纬傲,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件满败,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡叹括,警方通過(guò)查閱死者的電腦和手機(jī)算墨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)汁雷,“玉大人净嘀,你說(shuō)我怎么就攤上這事∠姥叮” “怎么了挖藏?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)厢漩。 經(jīng)常有香客問(wèn)我膜眠,道長(zhǎng),這世上最難降的妖魔是什么溜嗜? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任宵膨,我火速辦了婚禮,結(jié)果婚禮上粱胜,老公的妹妹穿的比我還像新娘。我一直安慰自己狐树,他們只是感情好焙压,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般涯曲。 火紅的嫁衣襯著肌膚如雪野哭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天幻件,我揣著相機(jī)與錄音拨黔,去河邊找鬼。 笑死绰沥,一個(gè)胖子當(dāng)著我的面吹牛篱蝇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播徽曲,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼零截,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秃臣?” 一聲冷哼從身側(cè)響起涧衙,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奥此,沒(méi)想到半個(gè)月后弧哎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稚虎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年撤嫩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祥绞。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡非洲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜕径,到底是詐尸還是另有隱情两踏,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布兜喻,位于F島的核電站梦染,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朴皆。R本人自食惡果不足惜帕识,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望遂铡。 院中可真熱鬧肮疗,春花似錦、人聲如沸扒接。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至碱呼,卻和暖如春蒙挑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背愚臀。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工忆蚀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姑裂。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓馋袜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親炭分。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桃焕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355