摘要:下面我將介紹的基本用法以及如何在異步編程中使用它們。在沒有發布之前,作為異步編程主力軍的回調函數一直被人詬病,其原因有太多比如回調地獄代碼執行順序難以追蹤后期因代碼變得十分復雜導致無法維護和更新等,而的出現在很大程度上改變了之前的窘境。
前言
自己著手準備寫這篇文章的初衷是覺得如果想要更深入的理解 JS,異步編程則是必須要跨過的一道坎。由于這里面涉及到的東西很多也很廣,在初學 JS 的時候可能無法完整的理解這一概念,即使在現在來看還是有很多自己沒有接觸和理解到的知識點,但是為了跨過這道坎,我仍然愿意鼓起勇氣用我已經掌握的部分知識盡全力講述一下 JS 中的異步編程。如果我所講的一些概念或術語有錯誤,請讀者向我指出問題所在,我會立即糾正更改。
同步與異步我們知道無論是在瀏覽器端還是在服務器 ( Node ) 端,JS 的執行都是在單線程下進行的。我們以瀏覽器中的 JS 執行線程為例,在這個線程中 JS 引擎會創建執行上下文棧,之后我們的代碼就會作為執行上下文 ( 全局、函數、eval ) 像一系列任務一樣在執行上下文棧中按照后進先出 ( LIFO ) 的方式依次執行。而同步最大的特性就是會阻塞后面任務的執行,比如此時 JS 正在執行大量的計算,這個時候就會使線程阻塞從而導致頁面渲染加載不連貫 ( 在瀏覽器端的 Event Loop 中每次執行棧中的任務執行完畢后都會去檢查并執行事件隊列里面的任務直到隊列中的任務為空,而事件隊列中的任務又分為微隊列與宏隊列,當微隊列中的任務執行完后才會去執行宏隊列中的任務,而在微隊列任務執行完到宏隊列任務開始之前瀏覽器的 GUI 線程會執行一次頁面渲染 ( UI rendering ),這也就解釋了為什么在執行棧中進行大量的計算時會阻塞頁面的渲染 ) 。
與同步相對的異步則可以理解為在異步操作完成后所要做的任務,它們通常以回調函數或者 Promise 的形式被放入事件隊列,再由事件循環 ( Event Loop ) 機制在每次輪詢時檢查異步操作是否完成,若完成則按事件隊列里面的執行規則來依次執行相應的任務。也正是得益于事件循環機制的存在,才使得異步任務不會像同步任務那樣完全阻塞 JS 執行線程。
異步操作一般包括 網絡請求 、文件讀取 、數據庫處理
異步任務一般包括 setTimout / setInterval 、Promise 、requestAnimationFrame ( 瀏覽器獨有 ) 、setImmediate ( Node 獨有 ) 、process.nextTick ( Node 獨有 ) 、etc ...
注意: 在瀏覽器端與在 Node 端的 Event Loop 機制是有所不同的,下面給出的兩張圖簡要闡述了在不同環境下事件循環的運行機制,由于 Event Loop 不是本文內容的重點,但是 JS 異步編程又是建立在它的基礎之上的,故在下面給出相應的閱讀鏈接,希望能夠幫助到有需要的讀者。
瀏覽器端
Node 端
閱讀鏈接
深入理解 JS 事件循環機制 ( 瀏覽器篇 )
深入理解 JS 事件循環機制 ( Node.js 篇 )
為異步而生的 JS 語法回望歷史,在最近幾年里 ECMAScript 標準幾乎每年都有版本的更新,也正是因為有像 ES6 這種在語言特性上大版本的更新,到了現今的 8102 年, JS 中的異步編程相對于那個只有回調函數的遠古時代有了很大的進步。下面我將介紹 callback 、Promise 、generator 、async / await 的基本用法以及如何在異步編程中使用它們。
callback回調函數并不算是 JS 中的語法但它卻是解決異步編程問題中最常用的一種方法,所以在這里有必要提出來,下面舉一個例子,大家看一眼就懂。
const foo = function (x, y, cb) { setTimeout(() => { cb(x + y) }, 2000) } // 使用 thunk 函數,有點函數柯里化的味道,在最后處理 callback。 const thunkify = function (fn) { return function () { let args = Array.from(arguments) return function (cb) { fn.apply(null, [...args, cb]) } } } let fooThunkory = thunkify(foo) let fooThunk1 = fooThunkory(2, 8) let fooThunk2 = fooThunkory(4, 16) fooThunk1((sum) => { console.log(sum) // 10 }) fooThunk2((sum) => { console.log(sum) // 20 })Promise
在 ES6 沒有發布之前,作為異步編程主力軍的回調函數一直被人詬病,其原因有太多比如回調地獄、代碼執行順序難以追蹤、后期因代碼變得十分復雜導致無法維護和更新等,而 Promise 的出現在很大程度上改變了之前的窘境。話不多說先直接上代碼提前感受下它的魅力,然后我再總結下自己認為在 Promise 中很重要的幾個點。
const foo = function () { let args = [...arguments] let cb = args.pop() setTimeout(() => { cb(...args) }, 2000) } const promisify = function (fn) { return function () { let args = [...arguments] return function (cb) { return new Promise((resolve, reject) => { fn.apply(null, [...args, resolve, reject, cb]) }) } } } const callback = function (x, y, isAdd, resolve, reject) { if (isAdd) { resolve(x + y) } else { reject("Add is not allowed.") } } let promisory = promisify(foo) let p1 = promisory(4, 16, false) let p2 = promisory(2, 8, true) p1(callback) .then((sum) => { console.log(sum) }, (err) => { console.error(err) // Add is not allowed. }) .finally(() => { console.log("Triggered once the promise is settled.") }) p2(callback) .then((sum) => { console.log(sum) // 10 return "evil
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98528.html
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
摘要:接下來,我們一起來看看中的異步編程,具體有哪幾種。實現異步編程的方法一回調函數上面不止一次提到了回調函數。它是異步編程中,最基本的方法。四對象接下來,我們聊聊與相關的異步編程方法,對象。 showImg(https://segmentfault.com/img/bVbneWy?w=1600&h=1200); 前言 最近,小伙伴S 問了我一段代碼: const funB = (value...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。寫一個符合規范并可配合使用的寫一個符合規范并可配合使用的理解的工作原理采用回調函數來處理異步編程。 JavaScript怎么使用循環代替(異步)遞歸 問題描述 在開發過程中,遇到一個需求:在系統初始化時通過http獲取一個第三方服務器端的列表,第三方服務器提供了一個接口,可通過...
摘要:回調函數,一般在同步情境下是最后執行的,而在異步情境下有可能不執行,因為事件沒有被觸發或者條件不滿足。同步方式請求異步同步請求當請求開始發送時,瀏覽器事件線程通知主線程,讓線程發送數據請求,主線程收到 一直以來都知道JavaScript是一門單線程語言,在筆試過程中不斷的遇到一些輸出結果的問題,考量的是對異步編程掌握情況。一般被問到異步的時候腦子里第一反應就是Ajax,setTimse...
摘要:異步編程解決方案筆記最近讀了樸靈老師的深入淺出中異步編程一章,并參考了一些有趣的文章。另外回調函數中的也失去了意義,這會使我們的程序必須依賴于副作用。 JavaScript 異步編程解決方案筆記 最近讀了樸靈老師的《深入淺出NodeJS》中《異步編程》一章,并參考了一些有趣的文章。在此做個筆記,記錄并鞏固學到的知識。 JavaScript異步編程的兩個核心難點 異步I/O、事件驅動使得...
摘要:調用棧被清空,消息隊列中并無任務,線程停止,事件循環結束。不確定的時間點請求返回,將設定好的回調函數放入消息隊列。調用棧執行完畢執行消息隊列任務。請求并發回調函數執行順序無法確定。 異步編程 JavaScript中異步編程問題可以說是基礎中的重點,也是比較難理解的地方。首先要弄懂的是什么叫異步? 我們的代碼在執行的時候是從上到下按順序執行,一段代碼執行了之后才會執行下一段代碼,這種方式...
閱讀 3359·2021-09-30 09:47
閱讀 2742·2021-08-18 10:22
閱讀 2527·2021-08-16 10:49
閱讀 2893·2019-08-30 15:53
閱讀 2738·2019-08-29 16:14
閱讀 3191·2019-08-28 18:18
閱讀 3237·2019-08-26 13:21
閱讀 794·2019-08-26 12:02