国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

web前端框架Javascript之JavaScript 異步編程史

這篇具有很好參考價值的文章主要介紹了web前端框架Javascript之JavaScript 異步編程史。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

早期的 Web 應(yīng)用中,與后臺進(jìn)行交互時,需要進(jìn)行 form 表單的提交,然后在頁面刷新后給用戶反饋結(jié)果。在頁面刷新過程中,后臺會重新返回一段 HTML 代碼,這段 HTML 中的大部分內(nèi)容與之前頁面基本相同,這勢必造成了流量的浪費,而且一來一回也延長了頁面的響應(yīng)時間,總是會讓人覺得 Web 應(yīng)用的體驗感比不上客戶端應(yīng)用。

2004 年,AJAX 即“Asynchronous JavaScript and XML”技術(shù)橫空出世,讓 Web 應(yīng)用的體驗得到了質(zhì)的提升。再到 2006 年,jQuery 問世,將 Web 應(yīng)用的開發(fā)體驗也提高到了新的臺階。

由于 JavaScript 語言單線程的特點,不管是事件的觸發(fā)還是 AJAX 都是通過回調(diào)的方式進(jìn)行異步任務(wù)的觸發(fā)。如果我們想要線性的處理多個異步任務(wù),在代碼中就會出現(xiàn)如下的情況:

getUser(token, function (user) {

getClassID(user, function (id) {

getClassName(id, function (name) {

  console.log(name)

})

})

})

我們經(jīng)常將這種代碼稱為:“回調(diào)地獄”。

事件與回調(diào)

眾所周知,JavaScript 的運行時是跑在單線程上的,是基于事件模型來進(jìn)行異步任務(wù)觸發(fā)的,不需要考慮共享內(nèi)存加鎖的問題,綁定的事件會按照順序齊齊整整的觸發(fā)。要理解 JavaScript 的異步任務(wù),首先就要理解 JavaScript 的事件模型。

由于是異步任務(wù),我們需要組織一段代碼放到未來運行(指定時間結(jié)束時或者事件觸發(fā)時),這一段代碼我們通常放到一個匿名函數(shù)中,通常稱為回調(diào)函數(shù)。

setTimeout(function () {

// 在指定時間結(jié)束時,觸發(fā)的回調(diào)

}, 800)

window.addEventListener(“resize”, function() {

// 當(dāng)瀏覽器視窗發(fā)生變化時,觸發(fā)的回調(diào)

})

未來運行

前面說過回調(diào)函數(shù)的運行是在未來,這就說明回調(diào)中使用的變量并不是在回調(diào)聲明階段就固定的。

for (var i = 0; i < 3; i++) {

setTimeout(function () {

console.log("i =", i)

}, 100)

}

這里連續(xù)聲明了三個異步任務(wù),100毫秒 后會輸出變量 i 的結(jié)果,按照正常的邏輯應(yīng)該會輸出 0、1、2這三個結(jié)果。

然而,事實并非如此,這也是我們剛開始接觸 JavaScript 的時候會遇到的問題,因為回調(diào)函數(shù)的實際運行時機(jī)是在未來,所以輸出的 i 的值是循環(huán)結(jié)束時的值,三個異步任務(wù)的結(jié)果一致,會輸出三個 i = 3。
web前端框架Javascript之JavaScript 異步編程史,IT,程序員,前端,前端,前端框架,javascript
經(jīng)歷過這個問題的同學(xué),一般都知道,我們可以通過閉包的方式,或者重新聲明局部變量的方式解決這個問題。

事件隊列

事件綁定之后,會將所有的回調(diào)函數(shù)存儲起來,然后在運行過程中,會有另外的線程對這些異步調(diào)用的回調(diào)進(jìn)行調(diào)度的處理,一旦滿足“觸發(fā)”條件就會將回調(diào)函數(shù)放入到對應(yīng)的事件隊列(這里只是簡單的理解成一個隊列,實際存在兩個事件隊列:宏任務(wù)、微任務(wù))中。

滿足觸發(fā)條件一般有以下幾種情況:

鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

DOM 相關(guān)的操作進(jìn)行的事件觸發(fā),比如點擊、移動、失焦等行為;

IO 相關(guān)的操作,文件讀取完成、網(wǎng)絡(luò)請求結(jié)束等;

時間相關(guān)的操作,到達(dá)定時任務(wù)的約定時間;

上面的這些行為發(fā)生時,代碼中之前指定的回調(diào)函數(shù)就會被放入一個任務(wù)隊列中,主線程一旦空閑,就會將其中的任務(wù)按照先進(jìn)先出的流程一一執(zhí)行。當(dāng)有新的事件被觸發(fā)時,又會重新放入到回調(diào)中,如此循環(huán)???,所以 JavaScript 的這一機(jī)制通常被稱為“事件循環(huán)機(jī)制”。

for (var i = 1; i <= 3; i++) {

const x = i

setTimeout(function () {

console.log(`第${x}個setTimout被執(zhí)行`)

}, 100)

}

可以看到,其運行順序滿足隊列先進(jìn)先出的特點,先聲明的先被執(zhí)行。
web前端框架Javascript之JavaScript 異步編程史,IT,程序員,前端,前端,前端框架,javascript
線程的阻塞

由于 JavaScript 單線程的特點,定時器其實并不可靠,當(dāng)代碼遇到阻塞的情況,即使事件到達(dá)了觸發(fā)的時間,也會一直等在主線程空閑才會運行。

const start = Date.now()

setTimeout(function () {

console.log(實際等待時間: ${Date.now() - start}ms)

}, 300)

// while循環(huán)讓線程阻塞 800ms

while(Date.now() - start < 800) {}

上面代碼中,定時器設(shè)置了 300ms 后觸發(fā)回調(diào)函數(shù),如果代碼沒有遇到阻塞,正常情況下會 300ms后,會輸出等待時間。

但是我們在還沒加了一個 while 循環(huán),這個循環(huán)會在 800ms 后才結(jié)束,主線程一直被這個循環(huán)阻塞在這里,導(dǎo)致時間到了回調(diào)函數(shù)也沒有正常運行。
web前端框架Javascript之JavaScript 異步編程史,IT,程序員,前端,前端,前端框架,javascript
Promise

事件回調(diào)的方式,在編碼的過程中,就特別容易造成回調(diào)地獄。而 Promise 提供了一種更加線性的方式編寫異步代碼,有點類似于管道的機(jī)制。

// 回調(diào)地獄

getUser(token, function (user) {

getClassID(user, function (id) {

getClassName(id, function (name) {

  console.log(name)

})

})

})

// Promise

getUser(token).then(function (user) {

return getClassID(user)

}).then(function (id) {

return getClassName(id)

}).then(function (name) {

console.log(name)

}).catch(function (err) {

console.error(‘請求異?!? err)

})

Promise 在很多語言中都有類似的實現(xiàn),在 JavaScript 發(fā)展過程中,比較著名的框架 jQuery、Dojo 也都進(jìn)行過類似的實現(xiàn)。2009 年,推出的 CommonJS 規(guī)范中,基于 Dojo.Deffered 的實現(xiàn)方式,提出 Promise/A 規(guī)范。也是這一年 Node.js 橫空出世,Node.js 很多實現(xiàn)都是依照 CommonJS 規(guī)范來的,比較熟悉的就是其模塊化方案。

早期的 Node.js 中也實現(xiàn)了 Promise 對象,但是 2010 年的時候,Ry(Node.js 作者)認(rèn)為 Promise 是一種比較上層的實現(xiàn),而且 Node.js 的開發(fā)本來就依賴于 V8 引擎,V8 引擎原生也沒有提供 Promise 的支持,所以后來 Node.js 的模塊使用了 error-first callback 的風(fēng)格(cb(error, result))。

const fs = require(‘fs’)

// 第一個參數(shù)為 Error 對象,如果不為空,則表示出現(xiàn)異常

fs.readFile(‘./README.txt’, function (err, buffer) {

if (err !== null) {

return

}

console.log(buffer.toString())

})

這一決定也導(dǎo)致后來 Node.js 中出現(xiàn)了各式各樣的 Promise 類庫,比較出名的就是 Q.js、Bluebird。關(guān)于 Promise 的實現(xiàn),之前有寫過一篇文章,感興趣可以看看:《手把手教你實現(xiàn) Promise》。

在 Node.js@8 之前,V8 原生的 Promise 實現(xiàn)有一些性能問題,導(dǎo)致原生 Promise 的性能甚至不如一些第三方的 Promise 庫。
web前端框架Javascript之JavaScript 異步編程史,IT,程序員,前端,前端,前端框架,javascript
所以,低版本的 Node.js 項目中,經(jīng)常會將 Promise 進(jìn)行全局的替換:

const Bulebird = require(‘bluebird’)

global.Promise = Bulebird

Generator & co

Generator(生成器) 是 ES6 提供的一種新的函數(shù)類型,主要是用于定義一個能自我迭代的函數(shù)。通過 function * 的語法能夠構(gòu)造一個 Generator 函數(shù),函數(shù)執(zhí)行后會返回一個iteration(迭代器)對象,該對象具有一個 next() 方法,每次調(diào)用 next() 方法就會在 yield 關(guān)鍵詞前面暫停,直到再次調(diào)用 next() 方法。

function * forEach(array) {

const len = array.length

for (let i = 0; i < len; i ++) {

yield i;

}

}

const it = forEach([2, 4, 6])

it.next() // { value: 2, done: false }

it.next() // { value: 4, done: false }

it.next() // { value: 6, done: false }

it.next() // { value: undefined, done: true }

next() 方法會返回一個對象,對象有兩個屬性 value、done:

value:表示 yield 后面的值;

done:表示函數(shù)是否執(zhí)行完畢;

由于生成器函數(shù)具有中斷執(zhí)行的特點,將生成器函數(shù)當(dāng)做一個異步操作的容器,再配合上 Promise 對象的 then 方法可以將交回異步邏輯的執(zhí)行權(quán),在每個 yeild 后面都加上一個 Promise 對象,就能讓迭代器不停的往下執(zhí)行。

function * gen(token) {

const user = yield getUser(token)

const cId = yield getClassID(user)

const name = yield getClassName(cId)

console.log(name)

}

const g = gen(‘xxxx-token’)

// 執(zhí)行 next 方法返回的 value 為一個 Promise 對象

const { value: promise1 } = g.next()

promise1.then(user => {

// 傳入第二個 next 方法的值,會被生成器中第一個 yield 關(guān)鍵詞前面的變量接受

// 往后推也是如此,第三個 next 方法的值,會被第二個 yield 前面的變量接受

// 只有第一個 next 方法的值會被拋棄

const { value: promise2 } = gen.next(user).value

promise2.then(cId => {

const { value: promise3, done } = gen.next(cId).value

// 依次先后傳遞,直到 next 方法返回的 done 為 true

})

})

我們將上面的邏輯進(jìn)行一下抽象,讓每個 Promise 對象正常返回后,就自動調(diào)用 next,讓迭代器進(jìn)行自執(zhí)行,直到執(zhí)行完畢(也就是 done 為 true)。

function co(gen, …args) {

const g = gen(…args)

function next(data) {

const { value: promise, done } = g.next(data)

if (done) return promise

promise.then(res => {

  next(res) // 將 promise 的結(jié)果傳入下一個 yield

})

}

next() // 開始自執(zhí)行

}

co(gen, ‘xxxx-token’)

這也就是 koa 早期的核心庫 co 的實現(xiàn)邏輯,只是 co 進(jìn)行了一些參數(shù)校驗與錯誤處理。通過 generator 加上 co 能夠讓異步流程更加的簡單易讀,對開發(fā)者而言肯定是階段歡喜的一件事。

async/await

async/await 可以說是 JavaScript 異步變成的解決方案,其實本質(zhì)上就是 Generator & co 的一個語法糖,只需要在異步的生成器函數(shù)前加上 async,然后將生成器函數(shù)內(nèi)的 yield 替換為 await。

async function fun(token) {

const user = await getUser(token)

const cId = await getClassID(user)

const name = await getClassName(cId)

console.log(name)

}

fun()

async 函數(shù)將自執(zhí)行器進(jìn)行了內(nèi)置,同時 await 后不限制為 Promise 對象,可以為任意值,而且 async/await 在語義上比起生成器的 yield 更加清楚,一眼就能明白這是一個異步操作。

文章來源:網(wǎng)絡(luò) 版權(quán)歸原作者所有

上文內(nèi)容不用于商業(yè)目的,如涉及知識產(chǎn)權(quán)問題,請權(quán)利人聯(lián)系小編,我們將立即處理文章來源地址http://www.zghlxwxcb.cn/news/detail-623761.html

到了這里,關(guān)于web前端框架Javascript之JavaScript 異步編程史的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • JavaScript 異步編程解決方案-中篇

    JavaScript 異步編程解決方案-中篇

    1.Promise 構(gòu)造函數(shù):new Promise(executor) Promise() 只能通過 new 運算符來構(gòu)造。如果嘗試在沒有使用 new 的情況下調(diào)用它,會拋出 TypeError 異常。 1.executor 執(zhí)行器函數(shù):(resolve,reject)={} 2.resolve 函數(shù):內(nèi)部定義成功時候調(diào)用values={} 3.reject 函數(shù):內(nèi)部定義失敗時候調(diào)用error={} 備注:e

    2024年01月23日
    瀏覽(23)
  • [javascript核心-04]徹底弄懂Promise異步編程

    本文github地址:JavaScript_Interview_Everything 大前端知識體系與面試寶典,從前端到后端,全棧工程師,成為六邊形戰(zhàn)士 1.1. 快速上手 01快手上手.js 02.若傳入的是另一個promise對象,則狀態(tài)由傳入的promise對象決定 03.若傳入了一個實現(xiàn)了 then 方法的對象,則執(zhí)行該then方法且由此方法

    2024年02月08日
    瀏覽(22)
  • defer 和 async:JavaScript異步編程的利器

    defer 和 async:JavaScript異步編程的利器

    ?? 前端開發(fā)工程師、技術(shù)日更博主、已過CET6 ?? 阿珊和她的貓_ CSDN 博客專家、23年度博客之星前端領(lǐng)域TOP1 ?? ???高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》 ?? 藍(lán)橋云課 簽約作者、上架課程《Vue.js 和 Egg.js 開發(fā)企業(yè)級健康管理項目》、《帶你

    2024年03月24日
    瀏覽(20)
  • 《JavaScript前端開發(fā)案例教程》課后習(xí)題及答案(黑馬程序員編著)

    一、填空題 1.window.document.body可以簡寫為______。 2.console.log(alert(‘Hello’))在控制臺的輸出結(jié)果是______。 3.編輯器中“以UTF-8無BOM格式編碼”中的BOM指的是______。 4.alert(‘測試’.length)的輸出結(jié)果是______。 二、判斷題 1.JavaScript是Java語言的腳本形式。( ) 2.JavaScript中的方法名不

    2024年02月09日
    瀏覽(96)
  • JavaScript編程技巧:將異步方法轉(zhuǎn)換為同步執(zhí)行的實用方法

    當(dāng)在JavaScript中處理異步操作時,我們通常會使用 async/await 來簡化異步代碼的編寫和理解。然而,有時候我們可能需要將異步方法轉(zhuǎn)換為同步執(zhí)行的方法,以滿足特定的需求。在本篇博客中,我們將詳細(xì)討論如何將異步方法轉(zhuǎn)換為同步執(zhí)行的方法。 異步方法的主要特點是非阻

    2024年02月08日
    瀏覽(40)
  • 加油優(yōu)惠價格計算-課后程序(JavaScript前端開發(fā)案例教程-黑馬程序員編著-第2章-課后作業(yè))

    加油優(yōu)惠價格計算-課后程序(JavaScript前端開發(fā)案例教程-黑馬程序員編著-第2章-課后作業(yè))

    一、案例描述 考核知識點 if 、 if…else 、if…else if…else 練習(xí)目標(biāo) 掌握if單分支語句。 掌握if…else雙分支語句 掌握if…else if…else多分支語句 需求分析 加油站,為了鼓勵車主多加油,實行多加多優(yōu)惠政策,具體優(yōu)惠如下: 已知92號汽油,每升6元;如果大于等于20升,那么每

    2024年02月07日
    瀏覽(108)
  • 深入理解Async/Await:從原理到實踐的JavaScript異步編程指南

    深入理解Async/Await:從原理到實踐的JavaScript異步編程指南

    理解 async/await 的原理和使用方法是理解現(xiàn)代JavaScript異步編程的關(guān)鍵。這里我會提供一個詳細(xì)的實例,涵蓋原理、流程、使用方法以及一些注意事項。代碼注釋會盡量詳盡,確保你理解每個步驟。 實例:使用async/await進(jìn)行異步操作 詳細(xì)解釋和注釋: 異步函數(shù)定義: async func

    2024年02月05日
    瀏覽(76)
  • Web前端-JavaScript

    Web前端-JavaScript

    目錄 1 概述 2 HTML嵌入JS代碼三種方式 2.1 第一種方式 2.2 第二種方式 2.3 第三種方式 3 變量 4 數(shù)據(jù)類型 4.1 概述 4.2 Number數(shù)據(jù)類型? 4.3 幾個值得注意的函數(shù) 4.4 Boolean數(shù)據(jù)類型? 4.5 String數(shù)據(jù)類型 4.6 關(guān)于Object類型 4.7 NaN、undefined、null的區(qū)別 4 函數(shù) 5 事件 5.1 JS中有哪些常用的事件

    2024年02月09日
    瀏覽(24)
  • Web前端 Javascript筆記3

    Web前端 Javascript筆記3

    ?內(nèi)存中的生命周期 ? ? ? ? 1、內(nèi)存分配 ? ? ? ? 2、內(nèi)存使用(讀寫) ? ? ? ? 3、內(nèi)存回收,使用完畢之后,垃圾回收器完成 ? ? ? ? 內(nèi)存泄漏:該回收的,由于某些未知因素,未釋放,叫做內(nèi)存泄漏 棧:數(shù)據(jù)存在其中會自動釋放 堆:對象,根據(jù)程序員的操作來決定釋

    2024年04月15日
    瀏覽(28)
  • 前端JavaScript企業(yè)框架的全面解析

    在現(xiàn)代Web開發(fā)中,前端JavaScript框架扮演著至關(guān)重要的角色。它們提供了豐富的功能和工具,幫助開發(fā)人員構(gòu)建功能強大且易于維護(hù)的企業(yè)級應(yīng)用程序。本篇博客將全面解析前端JavaScript企業(yè)框架,介紹其優(yōu)勢、使用場景和常見的框架選擇。 前端JavaScript企業(yè)框架是一套用于構(gòu)建

    2024年02月12日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包