91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中的異步處理方法

發布時間:2021-08-18 23:24:24 來源:億速云 閱讀:169 作者:chen 欄目:編程語言

本篇內容介紹了“JavaScript中的異步處理方法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

在 JavaScript 的世界中,所有代碼都是單線程執行的,由于這個“缺陷”,導致 JavaScript 的所有網絡操作,瀏覽器事件,都必須是異步執行。

異步執行可以用回調函數實現。

異步操作會在將來的某個時間點觸發一個函數調用。

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

一、回調函數(CallBack)

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

假設我們有一個 getData 方法,用于異步獲取數據,***個參數為請求的 url 地址,第二個參數是回調函數,如下:

function getData(url, callBack){     // 模擬發送網絡請求     setTimeout(()=> {         // 假設 res 就是返回的數據         var res = {             url: url,             data: Math.random()         }         // 執行回調,將數據作為參數傳遞         callBack(res)     }, 1000) }

我們預先設定一個場景,假設我們要請求三次服務器,每一次的請求依賴上一次請求的結果,如下:

getData('/page/1?param=123', (res1) => {     console.log(res1)     getData(`/page/2?param=${res1.data}`, (res2) => {         console.log(res2)         getData(`/page/3?param=${res2.data}`, (res3) => {             console.log(res3)         })     }) })
  • 通過上面的代碼可以看出,***次請求的 url 地址為: /page/1?param=123 ,返回結果為 res1 。

  • 第二個請求的 url 地址為: /page/2?param=${res1.data} ,依賴***次請求的 res1.data ,返回結果為  res2`。

  • 第三次請求的 url 地址為: /page/3?param=${res2.data} ,依賴第二次請求的 res2.data ,返回結果為 res3  。

由于后續請求依賴前一個請求的結果,所以我們只能把下一次請求寫到上一次請求的回調函數內部,這樣就形成了常說的:回調地獄。

二、發布/訂閱

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

這個模式有多種實現,下面采用的是Ben Alman的 Tiny Pub/Sub ,這是 jQuery 的一個插件

首先, f2 向”信號中心” jQuery 訂閱” done “信號

jQuery.subscribe("done", f2);

f1進行如下改寫

function f1(){ setTimeout(function(){ // f1的任務代碼 jQuery.publish("done"); }, 1000); }

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

jQuery.unsubscribe("done", f2);

這種方法的性質與”事件監聽”類似,但是明顯優于后者。因為我們可以通過查看”消息中心”,了解存在多少信號、每個信號有多少訂閱者,從而監控程序的運行。

三、Promise

Promise 是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大

所謂 Promise ,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說, Promise  是一個對象,從它可以獲取異步操作的消息。 Promise 提供統一的 API ,各種異步操作都可以用同樣的方法進行處理

簡單說,它的思想是,每一個異步任務返回一個 Promise 對象,該對象有一個 then 方法,允許指定回調函數。

現在我們使用 Promise 重新實現上面的案例,首先,我們要把異步請求數據的方法封裝成 Promise

function getDataAsync(url){     return new Promise((resolve, reject) => {         setTimeout(()=> {             var res = {                 url: url,                 data: Math.random()             }             resolve(res)         }, 1000)     }) }

那么請求的代碼應該這樣寫

getDataAsync('/page/1?param=123')     .then(res1=> {         console.log(res1)         return getDataAsync(`/page/2?param=${res1.data}`)     })     .then(res2=> {         console.log(res2)         return getDataAsync(`/page/3?param=${res2.data}`)     })     .then(res3=> {         console.log(res3)     })

then 方法返回一個新的 Promise 對象, then 方法的鏈式調用避免了 CallBack 回調地獄

但也并不是***,比如我們要添加很多 then 語句, 每一個 then 還是要寫一個回調。

如果場景再復雜一點,比如后邊的每一個請求依賴前面所有請求的結果,而不僅僅依賴上一次請求的結果,那會更復雜。 為了做的更好, async/await  就應運而生了,來看看使用 async/await 要如何實現

四、async/await

getDataAsync 方法不變,如下

 function getDataAsync(url){     return new Promise((resolve, reject) => {         setTimeout(()=> {             var res = {                 url: url,                 data: Math.random()             }             resolve(res)         }, 1000)     }) }

業務代碼如下

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

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

對比 Promise 感覺怎么樣?是不是非常清晰,但是 async/await 是基于 Promise 的,因為使用 async 修飾的方法最終返回一個  Promise , 實際上, async/await 可以看做是使用 Generator 函數處理異步的語法糖,我們來看看如何使用 Generator  函數處理異步

五、Generator

首先異步函數依然是

function getDataAsync(url){     return new Promise((resolve, reject) => {         setTimeout(()=> {             var res = {                 url: url,                 data: Math.random()             }             resolve(res)         }, 1000)     }) }

使用 Generator 函數可以這樣寫

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

然后我們這樣逐步執行

var g = getData() g.next().value.then(res1=> {     g.next(res1).value.then(res2=> {         g.next(res2).value.then(()=> {             g.next()         })     }) })

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

所以我們為其添加 then 方法, 在 then 方法里面接著運行 next 方法挪移遍歷器指針,直到 Generator  函數運行完成,實際上,這個過程我們不必手動完成,可以封裝成一個簡單的執行器

function run(gen){     var g = gen()      function next(data){         var res = g.next(data)         if (res.done) return res.value         res.value.then((data) => {             next(data)         })     }      next()  }

run 方法用來自動運行異步的 Generator 函數,其實就是一個遞歸的過程調用的過程。這樣我們就不必手動執行 Generator 函數了。 有了  run 方法,我們只需要這樣運行 getData 方法

run(getData)

這樣,我們就可以把異步操作封裝到 Generator 函數內部,使用 run 方法作為 Generator 函數的自執行器,來處理異步。其實我們不難發現,  async/await 方法相比于 Generator 處理異步的方式,有很多相似的地方,只不過 async/await 在語義化方面更加明顯,同時  async/await 不需要我們手寫執行器,其內部已經幫我們封裝好了,這就是為什么說 async/await 是 Generator  函數處理異步的語法糖了。

“JavaScript中的異步處理方法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沭阳县| 淳化县| 汉源县| 舞钢市| 清涧县| 佛坪县| 青州市| 无为县| 永清县| 商南县| 敖汉旗| 涿州市| 铜梁县| 体育| 雷州市| 徐州市| 同德县| 郑州市| 禄丰县| 凉城县| 桦南县| 许昌市| 洞口县| 大英县| 永州市| 新蔡县| 屏南县| 绩溪县| 扬中市| 昭苏县| 昭觉县| 义马市| 辽源市| 蒲城县| 青岛市| 乌拉特后旗| 青龙| 南丹县| 镶黄旗| 八宿县| 汤原县|