成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談JavaScript中的異步處理

開(kāi)發(fā) 后端
在 JavaScript 的世界中,所有代碼都是單線程執(zhí)行的,由于這個(gè)“缺陷”,導(dǎo)致 JavaScript 的所有網(wǎng)絡(luò)操作,瀏覽器事件,都必須是異步執(zhí)行。主流的異步處理方案主要有:回調(diào)函數(shù) (CallBack) 、 Promise 、 Generator 函數(shù)、 async/await 。

在 JavaScript 的世界中,所有代碼都是單線程執(zhí)行的,由于這個(gè)“缺陷”,導(dǎo)致 JavaScript 的所有網(wǎng)絡(luò)操作,瀏覽器事件,都必須是異步執(zhí)行。

異步執(zhí)行可以用回調(diào)函數(shù)實(shí)現(xiàn)。

異步操作會(huì)在將來(lái)的某個(gè)時(shí)間點(diǎn)觸發(fā)一個(gè)函數(shù)調(diào)用。

主流的異步處理方案主要有:回調(diào)函數(shù) (CallBack) 、 Promise 、 Generator 函數(shù)、 async/await 。

[[201412]]

一、回調(diào)函數(shù)(CallBack)

這是異步編程最基本的方法

假設(shè)我們有一個(gè) getData 方法,用于異步獲取數(shù)據(jù),***個(gè)參數(shù)為請(qǐng)求的 url 地址,第二個(gè)參數(shù)是回調(diào)函數(shù),如下:

 

  1. function getData(url, callBack){ 
  2.     // 模擬發(fā)送網(wǎng)絡(luò)請(qǐng)求 
  3.     setTimeout(()=> { 
  4.         // 假設(shè) res 就是返回的數(shù)據(jù) 
  5.         var res = { 
  6.             url: url, 
  7.             data: Math.random() 
  8.         } 
  9.         // 執(zhí)行回調(diào),將數(shù)據(jù)作為參數(shù)傳遞 
  10.         callBack(res) 
  11.     }, 1000) 

我們預(yù)先設(shè)定一個(gè)場(chǎng)景,假設(shè)我們要請(qǐng)求三次服務(wù)器,每一次的請(qǐng)求依賴上一次請(qǐng)求的結(jié)果,如下:

 

  1. getData('/page/1?param=123', (res1) => { 
  2.     console.log(res1) 
  3.     getData(`/page/2?param=${res1.data}`, (res2) => { 
  4.         console.log(res2) 
  5.         getData(`/page/3?param=${res2.data}`, (res3) => { 
  6.             console.log(res3) 
  7.         }) 
  8.     }) 
  9. }) 
  • 通過(guò)上面的代碼可以看出,***次請(qǐng)求的 url 地址為: /page/1?param=123 ,返回結(jié)果為 res1 。
  • 第二個(gè)請(qǐng)求的 url 地址為: /page/2?param=${res1.data} ,依賴***次請(qǐng)求的 res1.data ,返回結(jié)果為 res2`。
  • 第三次請(qǐng)求的 url 地址為: /page/3?param=${res2.data} ,依賴第二次請(qǐng)求的 res2.data ,返回結(jié)果為 res3 。

由于后續(xù)請(qǐng)求依賴前一個(gè)請(qǐng)求的結(jié)果,所以我們只能把下一次請(qǐng)求寫(xiě)到上一次請(qǐng)求的回調(diào)函數(shù)內(nèi)部,這樣就形成了常說(shuō)的:回調(diào)地獄。

二、發(fā)布/訂閱

我們假定,存在一個(gè)”信號(hào)中心”,某個(gè)任務(wù)執(zhí)行完成,就向信號(hào)中心”發(fā)布”( publish )一個(gè)信號(hào),其他任務(wù)可以向信號(hào)中心”訂閱”( subscribe )這個(gè)信號(hào),從而知道什么時(shí)候自己可以開(kāi)始執(zhí)行。這就叫做”發(fā)布/訂閱模式”(publish-subscribe pattern),又稱”觀察者模式”(observer pattern)

這個(gè)模式有多種實(shí)現(xiàn),下面采用的是Ben Alman的 Tiny Pub/Sub ,這是 jQuery 的一個(gè)插件

首先, f2 向”信號(hào)中心” jQuery 訂閱” done “信號(hào)

  1. jQuery.subscribe("done", f2); 

f1進(jìn)行如下改寫(xiě)

 

  1. function f1(){ 
  2.     setTimeout(function(){ 
  3.       // f1的任務(wù)代碼 
  4.       jQuery.publish("done"); 
  5.     }, 1000); 

jQuery.publish("done") 的意思是, f1 執(zhí)行完成后,向”信號(hào)中心 "jQuery 發(fā)布 "done" 信號(hào),從而引發(fā)f2的執(zhí)行。 此外,f2完成執(zhí)行后,也可以取消訂閱( unsubscribe )

  1. jQuery.unsubscribe("done", f2); 

這種方法的性質(zhì)與”事件監(jiān)聽(tīng)”類似,但是明顯優(yōu)于后者。因?yàn)槲覀兛梢酝ㄟ^(guò)查看”消息中心”,了解存在多少信號(hào)、每個(gè)信號(hào)有多少訂閱者,從而監(jiān)控程序的運(yùn)行。

三、Promise

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大

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

簡(jiǎn)單說(shuō),它的思想是,每一個(gè)異步任務(wù)返回一個(gè) Promise 對(duì)象,該對(duì)象有一個(gè) then 方法,允許指定回調(diào)函數(shù)。

現(xiàn)在我們使用 Promise 重新實(shí)現(xiàn)上面的案例,首先,我們要把異步請(qǐng)求數(shù)據(jù)的方法封裝成 Promise

 

  1. function getDataAsync(url){ 
  2.     return new Promise((resolve, reject) => { 
  3.         setTimeout(()=> { 
  4.             var res = { 
  5.                 url: url, 
  6.                 data: Math.random() 
  7.             } 
  8.             resolve(res) 
  9.         }, 1000) 
  10.     }) 

那么請(qǐng)求的代碼應(yīng)該這樣寫(xiě)

 

  1. getDataAsync('/page/1?param=123'
  2.     .then(res1=> { 
  3.         console.log(res1) 
  4.         return getDataAsync(`/page/2?param=${res1.data}`) 
  5.     }) 
  6.     .then(res2=> { 
  7.         console.log(res2) 
  8.         return getDataAsync(`/page/3?param=${res2.data}`) 
  9.     }) 
  10.     .then(res3=> { 
  11.         console.log(res3) 
  12.     }) 

then 方法返回一個(gè)新的 Promise 對(duì)象, then 方法的鏈?zhǔn)秸{(diào)用避免了 CallBack 回調(diào)地獄

但也并不是***,比如我們要添加很多 then 語(yǔ)句, 每一個(gè) then 還是要寫(xiě)一個(gè)回調(diào)。

如果場(chǎng)景再?gòu)?fù)雜一點(diǎn),比如后邊的每一個(gè)請(qǐng)求依賴前面所有請(qǐng)求的結(jié)果,而不僅僅依賴上一次請(qǐng)求的結(jié)果,那會(huì)更復(fù)雜。 為了做的更好, async/await 就應(yīng)運(yùn)而生了,來(lái)看看使用 async/await 要如何實(shí)現(xiàn)

四、async/await

getDataAsync 方法不變,如下

 

  1.  function getDataAsync(url){ 
  2.     return new Promise((resolve, reject) => { 
  3.         setTimeout(()=> { 
  4.             var res = { 
  5.                 url: url, 
  6.                 data: Math.random() 
  7.             } 
  8.             resolve(res) 
  9.         }, 1000) 
  10.     }) 

業(yè)務(wù)代碼如下

 

  1. async function getData(){ 
  2.     var res1 = await getDataAsync('/page/1?param=123'
  3.     console.log(res1) 
  4.     var res2 = await getDataAsync(`/page/2?param=${res1.data}`) 
  5.     console.log(res2) 
  6.     var res3 = await getDataAsync(`/page/2?param=${res2.data}`) 
  7.     console.log(res3) 

可以看到使用 async\await 就像寫(xiě)同步代碼一樣

對(duì)比 Promise 感覺(jué)怎么樣?是不是非常清晰,但是 async/await 是基于 Promise 的,因?yàn)槭褂?async 修飾的方法最終返回一個(gè) Promise , 實(shí)際上, async/await 可以看做是使用 Generator 函數(shù)處理異步的語(yǔ)法糖,我們來(lái)看看如何使用 Generator 函數(shù)處理異步

五、Generator

首先異步函數(shù)依然是

 

  1. function getDataAsync(url){ 
  2.     return new Promise((resolve, reject) => { 
  3.         setTimeout(()=> { 
  4.             var res = { 
  5.                 url: url, 
  6.                 data: Math.random() 
  7.             } 
  8.             resolve(res) 
  9.         }, 1000) 
  10.     }) 

使用 Generator 函數(shù)可以這樣寫(xiě)

 

  1. function*getData(){ 
  2.     var res1 = yield getDataAsync('/page/1?param=123'
  3.     console.log(res1) 
  4.     var res2 = yield getDataAsync(`/page/2?param=${res1.data}`) 
  5.     console.log(res2) 
  6.     var res3 = yield getDataAsync(`/page/2?param=${res2.data}`) 
  7.     console.log(res3)) 

然后我們這樣逐步執(zhí)行

 

  1. var g = getData() 
  2. g.next().value.then(res1=> { 
  3.     g.next(res1).value.then(res2=> { 
  4.         g.next(res2).value.then(()=> { 
  5.             g.next() 
  6.         }) 
  7.     }) 
  8. }) 

上面的代碼,我們逐步調(diào)用遍歷器的 next() 方法,由于每一個(gè) next() 方法返回值的 value 屬性為一個(gè) Promise 對(duì)象

所以我們?yōu)槠涮砑?then 方法, 在 then 方法里面接著運(yùn)行 next 方法挪移遍歷器指針,直到 Generator 函數(shù)運(yùn)行完成,實(shí)際上,這個(gè)過(guò)程我們不必手動(dòng)完成,可以封裝成一個(gè)簡(jiǎn)單的執(zhí)行器

 

  1. function run(gen){ 
  2.     var g = gen() 
  3.  
  4.     function next(data){ 
  5.         var res = g.next(data) 
  6.         if (res.done) return res.value 
  7.         res.value.then((data) => { 
  8.             next(data) 
  9.         }) 
  10.     } 
  11.  
  12.     next() 
  13.  

run 方法用來(lái)自動(dòng)運(yùn)行異步的 Generator 函數(shù),其實(shí)就是一個(gè)遞歸的過(guò)程調(diào)用的過(guò)程。這樣我們就不必手動(dòng)執(zhí)行 Generator 函數(shù)了。 有了 run 方法,我們只需要這樣運(yùn)行 getData 方法

  1. run(getData) 

這樣,我們就可以把異步操作封裝到 Generator 函數(shù)內(nèi)部,使用 run 方法作為 Generator 函數(shù)的自執(zhí)行器,來(lái)處理異步。其實(shí)我們不難發(fā)現(xiàn), async/await 方法相比于 Generator 處理異步的方式,有很多相似的地方,只不過(guò) async/await 在語(yǔ)義化方面更加明顯,同時(shí) async/await 不需要我們手寫(xiě)執(zhí)行器,其內(nèi)部已經(jīng)幫我們封裝好了,這就是為什么說(shuō) async/await 是 Generator 函數(shù)處理異步的語(yǔ)法糖了。

責(zé)任編輯:未麗燕 來(lái)源: Poetry's Blog
相關(guān)推薦

2020-04-07 00:10:16

javascrip語(yǔ)言異步

2009-03-11 15:30:05

evalwithJavascript

2017-08-22 16:40:22

前端JavaScript接口

2009-06-10 22:06:29

JavaScript面向?qū)ο?/a>

2023-11-29 07:38:33

JavaScript異步處理

2013-12-25 10:08:42

ember.js異步處理

2011-07-05 10:20:38

java

2014-06-05 09:29:03

數(shù)據(jù)處理

2013-03-26 10:27:01

JavaScriptjson

2011-07-14 10:58:26

JavaScript強(qiáng)制類型轉(zhuǎn)換函數(shù)

2009-06-24 10:49:16

JavaScript

2009-04-21 09:37:50

ASP.NETAjaxJavaScript

2009-06-18 12:21:07

javascriptdom

2015-05-06 10:02:26

2020-10-15 13:29:57

javascript

2010-10-08 10:03:52

JavaScript圖像

2009-08-21 11:02:55

C#異步調(diào)用

2018-11-08 15:30:04

JavaScriptES6異步

2010-12-01 14:34:59

AsyncTask異步處理任務(wù)Android

2025-02-13 13:14:49

JavaScriptnullundefined
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 三级av免费| 一区二区电影 | 精品一区二区视频 | 欧美日韩亚洲一区 | 国产美女精品视频 | 国产精品一区二区欧美黑人喷潮水 | 久久久久久久久久久久久91 | 午夜成人免费电影 | 综合色在线 | 久久日韩粉嫩一区二区三区 | 精品99爱视频在线观看 | 国产精品免费视频一区 | 夜夜操操操 | 热久久免费视频 | 性色在线 | 污视频免费在线观看 | 欧美日韩在线免费观看 | 亚洲福利 | 国产在线视频一区二区 | 日本淫视频 | 日韩视频精品在线 | 美女逼网站 | 久久y| 日韩日韩日韩日韩日韩日韩日韩 | 亚洲综合成人网 | www.888www看片| 欧美在线一区二区三区四区 | 91国自产 | 欧美午夜在线 | 国产日韩欧美另类 | 天天夜碰日日摸日日澡 | 国产欧美日韩一区 | 欧美一区二区三区,视频 | 亚洲最大看片网站 | 亚洲一区二区三区在线视频 | 精品久久久久久久人人人人传媒 | 精品久久久久久亚洲综合网 | 亚洲第一天堂 | 精品国产一区二区国模嫣然 | 国产精品爱久久久久久久 | 精品乱码一区二区 |