日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

如何在現(xiàn)代JavaScript中編寫異步任務(wù)

瀏覽:27日期:2023-06-10 08:44:15
前言

在本文中,我們將探討過去異步執(zhí)行的 JavaScript 的演變,以及它是怎樣改變我們編寫代碼的方式的。我們將從最早的 Web 開發(fā)開始,一直到現(xiàn)代異步模式。

作為編程語(yǔ)言, JavaScript 有兩個(gè)主要特征,這兩個(gè)特征對(duì)于理解我們的代碼如何工作非常重要。首先是它的同步特性,這意味著代碼將逐行運(yùn)行,其次是單線程,任何時(shí)候都僅執(zhí)行一個(gè)命令。

隨著語(yǔ)言的發(fā)展,允許異步執(zhí)行的新工件出現(xiàn)在場(chǎng)景中。開發(fā)人員在解決更復(fù)雜的算法和數(shù)據(jù)流時(shí)嘗試了不同的方法,從而導(dǎo)致新的接口和模式出現(xiàn)。

同步執(zhí)行和觀察者模式

如簡(jiǎn)介中所述,JavaScript 通常會(huì)逐行運(yùn)行你編寫的代碼。即使在最初的幾年中,該語(yǔ)言也有這種規(guī)則的例外,盡管很少,你可能已經(jīng)知道了它們:HTTP 請(qǐng)求,DOM 事件和time interval。

如果我們通過添加事件偵聽器去響應(yīng)用戶對(duì)元素的單擊,則無論語(yǔ)言解釋器在運(yùn)行什么,它都會(huì)停止,然后運(yùn)行在偵聽器回調(diào)中編寫的代碼,之后再返回正常的流程。

與 interval 或網(wǎng)絡(luò)請(qǐng)求相同,addEventListener,setTimeout 和 XMLHttpRequest 是 Web 開發(fā)人員訪問異步執(zhí)行的第一批工件。

盡管這些是 JavaScript 中同步執(zhí)行的例外情況,但重要的是你要了解該語(yǔ)言仍然是單線程的。我們可以打破這種同步性,但是解釋器仍然每次運(yùn)行一行代碼。

例如檢查一個(gè)網(wǎng)絡(luò)請(qǐng)求。

var request = new XMLHttpRequest();request.open(’GET’, ’//some.api.at/server’, true);// observe for server responserequest.onreadystatechange = function() { if (request.readyState === 4 && xhr.status === 200) { console.log(request.responseText); }}11request.send();

不管發(fā)生什么情況,當(dāng)服務(wù)器恢復(fù)運(yùn)行時(shí),分配給 onreadystatechange 的方法都會(huì)在取回程序的代碼序列之前被調(diào)用。

對(duì)用戶交互做出反應(yīng)時(shí),也會(huì)發(fā)生類似的情況。

const button = document.querySelector(’button’);// observe for user interactionbutton.addEventListener(’click’, function(e) { console.log(’user click just happened!’);})

你可能會(huì)注意到,我們正在連接一個(gè)外部事件并傳遞一個(gè)回調(diào),告訴代碼當(dāng)事件發(fā)生時(shí)應(yīng)該怎么做。十多年前,“什么是回調(diào)?”是一個(gè)非常受期待的面試問題,因?yàn)樵诤芏啻a庫(kù)中到處都有這種模式。

在上述每種情況下,我們都在響應(yīng)外部事件。不管是達(dá)到一定的時(shí)間間隔、用戶操作還是服務(wù)器響應(yīng)。我們本身無法創(chuàng)建異步任務(wù),我們總是 觀察 發(fā)生在我們力所能及范圍之外的事件。

這就是為什么這種方式的代碼被稱為觀察者模式的原因,在這種情況下,它最好由 addEventListener 接口來表示。很快,暴露這種模式的事件發(fā)送器庫(kù)或框架開始蓬勃發(fā)展。

NODE.JS 和事件發(fā)送器

Node.js 是一個(gè)很好的例子,它的官網(wǎng)把自己描述為“異步事件驅(qū)動(dòng)的 JavaScript 運(yùn)行時(shí)”,所以事件發(fā)送器和回調(diào)是一等公民。它甚至已經(jīng)實(shí)現(xiàn)了一個(gè) EventEmitter 構(gòu)造函數(shù)。

const EventEmitter = require(’events’);const emitter = new EventEmitter();// respond to eventsemitter.on(’greeting’, (message) => console.log(message));// send eventsemitter.emit(’greeting’, ’Hi there!’);

這不僅是通用的異步執(zhí)行方法,而且是其生態(tài)系統(tǒng)的核心模式和慣例。Node.js 開辟了一個(gè)在不同環(huán)境中甚至在 web 之外編寫 JavaScript 的新時(shí)代。當(dāng)然異步的情況也是可能的,例如創(chuàng)建新目錄或?qū)懳募?/p>

const { mkdir, writeFile } = require(’fs’);const styles = ’body { background: #ffdead; }’;mkdir(’./assets/’, (error) => { if (!error) { writeFile(’assets/main.css’, styles, ’utf-8’, (error) => { if (!error) console.log(’stylesheet created’); }) }})

你可能會(huì)注意到,回調(diào)函數(shù)將第一個(gè)參數(shù)接作為 error ,如果得到了預(yù)期的響應(yīng)數(shù)據(jù),則將其作為第二個(gè)參數(shù)。這就是所謂的錯(cuò)誤優(yōu)先回調(diào)模式,它成為作者和貢獻(xiàn)者為包和庫(kù)所做的約定。

Promise 和沒完沒了的回調(diào)鏈

隨著 Web 開發(fā)面臨的更復(fù)雜的問題,出現(xiàn)了對(duì)更好的異步工件的需求。如果我們查看最后一個(gè)代碼段,則會(huì)看到重復(fù)的回調(diào)鏈,隨著任務(wù)數(shù)量的增加,回調(diào)鏈的擴(kuò)展效果不佳。

例如,我們僅添加兩個(gè)步驟,即文件讀取和樣式預(yù)處理。

const { mkdir, writeFile, readFile } = require(’fs’);const less = require(’less’)readFile(’./main.less’, ’utf-8’, (error, data) => { if (error) throw error less.render(data, (lessError, output) => { if (lessError) throw lessError mkdir(’./assets/’, (dirError) => { if (dirError) throw dirError writeFile(’assets/main.css’, output.css, ’utf-8’, (writeError) => { if (writeError) throw writeError console.log(’stylesheet created’); }) }) })16})

我們可以看到,由于多個(gè)回調(diào)鏈和重復(fù)的錯(cuò)誤處理,編寫程序變得越來越復(fù)雜,代碼變得更加難以理解。

Promise、包裝和鏈模式

當(dāng) Promises 最初被宣布為 JavaScript 語(yǔ)言的新成員時(shí),并沒有引起太多關(guān)注,它們并不是一個(gè)新概念,因?yàn)槠渌Z(yǔ)言在幾十年前就已經(jīng)實(shí)現(xiàn)了類似的實(shí)現(xiàn)。事實(shí)上自從它出現(xiàn)以來,他們就改變了我從事的大多數(shù)項(xiàng)目的語(yǔ)義和結(jié)構(gòu)。

Promises不僅為開發(fā)人員引入了用于編寫異步代碼的內(nèi)置解決方案,,而且還開辟了Web 開發(fā)的新階段,成為 Web 規(guī)范后來的新功能(如 fetch)的構(gòu)建基礎(chǔ)。

從回調(diào)方法遷移到基于 promise 的方法在項(xiàng)目(例如庫(kù)和瀏覽器)中變得越來越普遍,甚至 Node.js 也開始緩慢地遷移到它上面。

例如,包裝 Node 的 readFile 方法:

const { readFile } = require(’fs’);const asyncReadFile = (path, options) => { return new Promise((resolve, reject) => { readFile(path, options, (error, data) => { if (error) reject(error); else resolve(data); }) });}

在這里,我們通過在 Promise 構(gòu)造函數(shù)內(nèi)部執(zhí)行來隱藏回調(diào),方法成功后調(diào)用 resolve,定義錯(cuò)誤對(duì)象時(shí)調(diào)用reject。

當(dāng)一個(gè)方法返回一個(gè) Promise 對(duì)象時(shí),我們可以通過將一個(gè)函數(shù)傳遞給 then 來遵循其成功的解析,它的參數(shù)是 Promise 被解析的值,在這里是 data。

如果在方法運(yùn)行期間拋出錯(cuò)誤,則將調(diào)用 catch 函數(shù)(如果存在)。

注意:如果你需要更深入地了解 Promise 的工作原理,建議你看 Jake Archibald 在 Google 的 web 開發(fā)博客上寫的文章“ JavaScript Promises:簡(jiǎn)介”。

現(xiàn)在我們可以使用這些新方法并避免回調(diào)鏈。

asyncRead(’./main.less’, ’utf-8’) .then(data => console.log(’file content’, data)) .catch(error => console.error(’something went wrong’, error))

它具有創(chuàng)建異步任務(wù)的原生方法,并以清晰的接口跟蹤其可能的結(jié)果,這擺脫了觀察者模式。基于 Promise 的代碼似乎可以解決可讀性差且容易出錯(cuò)的代碼。

在更好的語(yǔ)法突出顯示和更清晰的錯(cuò)誤提示信息對(duì)編碼過程中提供的幫助下,對(duì)于開發(fā)人員來說,編寫更容易理解的代碼變得更具可預(yù)測(cè)性,并且執(zhí)行的情況更好,更容易發(fā)現(xiàn)可能的陷阱。

Promises 的采用在社區(qū)中非常普遍,以至于 Node.js 迅速發(fā)布其 I/O 方法的內(nèi)置版本以返回 Promise 對(duì)象,例如從 fs.promises 中導(dǎo)入文件操作。

它甚至提供了一個(gè) promisify 工具來包裝遵循錯(cuò)誤優(yōu)先回調(diào)模式的函數(shù),并將其轉(zhuǎn)換為基于 Promise 的函數(shù)。

但是 Promise 在所有情況下都能提供幫助嗎?

讓我們重新評(píng)估一下用 Promise 編寫的樣式預(yù)處理任務(wù)。

const { mkdir, writeFile, readFile } = require(’fs’).promises;const less = require(’less’)readFile(’./main.less’, ’utf-8’) .then(less.render) .then(result => mkdir(’./assets’) .then(writeFile(’assets/main.css’, result.css, ’utf-8’)) ) .catch(error => console.error(error))

代碼中的冗余明顯減少了,尤其是在錯(cuò)誤處理方面,因?yàn)槲覀儸F(xiàn)在依賴于 catch,但是 Promise 在某種程度上沒能提供直接與動(dòng)作串聯(lián)相關(guān)的清晰代碼縮進(jìn)。

實(shí)際上,這是在調(diào)用 readFile 之后的第一個(gè) then 語(yǔ)句中實(shí)現(xiàn)的。這些代碼行之后發(fā)生的事情是需要?jiǎng)?chuàng)建一個(gè)新的作用域,我們可以在該作用域中先創(chuàng)建目錄,然后將結(jié)果寫入文件中。這會(huì)導(dǎo)致縮進(jìn)節(jié)奏的中斷,乍一看就不容易確定指令序列。

注意:請(qǐng)注意,這是一個(gè)示例程序,我們可以控制某些方法,它們都遵循行業(yè)慣例,但并非總是如此。通過更復(fù)雜的串聯(lián)或引入不同的庫(kù),我們的代碼風(fēng)格可以輕松被打破。

令人高興的是,JavaScript 社區(qū)再次從其他語(yǔ)言的語(yǔ)法中學(xué)到了東西,并增加了一種表示方法,可以在大多數(shù)情況下幫助異步任務(wù)串聯(lián),而不是像同步代碼那樣能夠令人輕松的閱讀。

Async 與 Await

Promise 被定義為執(zhí)行時(shí)的未解決的值,創(chuàng)建 Promise 實(shí)例是對(duì)此工件的“顯式”調(diào)用。

const { mkdir, writeFile, readFile } = require(’fs’).promises;const less = require(’less’)readFile(’./main.less’, ’utf-8’) .then(less.render) .then(result => mkdir(’./assets’) .then(writeFile(’assets/main.css’, result.css, ’utf-8’)) ) .catch(error => console.error(error))

在異步方法內(nèi)部,我們可以用 await 保留字來確定 Promise 的解決方案,然后再繼續(xù)執(zhí)行。

讓我們用這種語(yǔ)法重新編寫代碼段。

const { mkdir, writeFile, readFile } = require(’fs’).promises;const less = require(’less’)async function processLess() { const content = await readFile(’./main.less’, ’utf-8’) const result = await less.render(content) await mkdir(’./assets’) await writeFile(’assets/main.css’, result.css, ’utf-8’)}11processLess()

注意:請(qǐng)注意,我們需要將所有代碼移至某個(gè)方法中,因?yàn)槲覀儫o法在 異步函數(shù)的作用域之外使用 await 。

每當(dāng)異步方法找到一個(gè) await 語(yǔ)句時(shí),它將停止執(zhí)行,直到 promise 被解決為止。

盡管是異步執(zhí)行,但用 async/await 表示會(huì)使代碼看起來好像是同步的,這是容易被開發(fā)人員閱讀和理解的東西。

那么錯(cuò)誤處理呢?我們可以用在語(yǔ)言中存在了很久的try 和 catch。

const { mkdir, writeFile, readFile } = require(’fs’).promises;const less = require(’less’)async function processLess() { const content = await readFile(’./main.less’, ’utf-8’) const result = await less.render(content) await mkdir(’./assets’) await writeFile(’assets/main.css’, result.css, ’utf-8’)}try { processLess()} catch (e) { console.error(e)}

我們大可放心,在過程中拋出的任何錯(cuò)誤都會(huì)由 catch 語(yǔ)句中的代碼處理。現(xiàn)在我們有了一個(gè)易于閱讀和規(guī)范的代碼。

對(duì)返回值進(jìn)行的后續(xù)操作無需存儲(chǔ)在不會(huì)破壞代碼節(jié)奏的 mkdir 之類的變量中;也無需在以后的步驟中創(chuàng)建新的作用域來訪問 result 的值。

可以肯定地說,Promise 是該語(yǔ)言中引入的基本工件,對(duì)于在 JavaScript 中啟用 async/await 表示法是必需的,你可以在現(xiàn)代瀏覽器和最新版本的 Node.js 中使用它。

注意:最近在 JSConf 中,Node 的創(chuàng)建者和第一貢獻(xiàn)者 Ryan Dahl, 對(duì)在其早期開發(fā)中沒有遵守Promises 表示遺憾,主要是因?yàn)?Node 的目標(biāo)是創(chuàng)建事件驅(qū)動(dòng)服務(wù)器和文件管理,而 Observer 模式更適合這樣。

結(jié)論

將 Promise 引入 Web 開發(fā)的目的是改變我們?cè)诖a中順序操作的方式,并改變了我們理解代碼的方式以及編寫庫(kù)和包的方式。

但是擺脫回調(diào)鏈更難解決,我認(rèn)為在多年來習(xí)慣于觀察者模式和采用的方法之后,必須將方法傳遞給 then 并不能幫助我們擺脫原有的思路,例如 Node.js。

正如 Nolan Lawson 在他的出色文章“關(guān)于 Promise 級(jí)聯(lián)的錯(cuò)誤使用“【https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html】 中所述,舊的回調(diào)習(xí)慣是死硬且頑固的!在文中他解釋了如何避免這些陷阱。

我認(rèn)為 Promise 是中間步驟,它允許以自然的方式生成異步任務(wù),但并沒有幫助我們進(jìn)一步改進(jìn)更好的代碼模式,有時(shí)你需要更適應(yīng)改進(jìn)的語(yǔ)言語(yǔ)法。

當(dāng)嘗試使用JavaScript解決更復(fù)雜的難題時(shí),我們看到了對(duì)更成熟語(yǔ)言的需求,并且我們嘗試了以前不曾在網(wǎng)上看到的體系結(jié)構(gòu)和模式。

我們?nèi)匀徊恢?ECMAScript 規(guī)范在幾年后的樣子,因?yàn)槲覀円恢痹趯?JavaScript 治理擴(kuò)展到 web 之外,并嘗試解決更復(fù)雜的難題。

現(xiàn)在很難說我們需要從語(yǔ)言中真正地將這些難題轉(zhuǎn)變成更簡(jiǎn)單的程序,但是我對(duì) Web 和 JavaScript 本身如何推動(dòng)技術(shù),試圖適應(yīng)挑戰(zhàn)和新環(huán)境感到滿意。與十年前剛剛開始在瀏覽器中編寫代碼時(shí)相比,我覺得現(xiàn)在 JavaScript 是“異步友好”的。

原文:https://www.smashingmagazine.com/2019/10/asynchronous-tasks-modern-javascript/

到此這篇關(guān)于如何在現(xiàn)代JavaScript中編寫異步任務(wù)的文章就介紹到這了,更多相關(guān)JavaScript編寫異步任務(wù)內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
不卡福利视频| 日韩中文字幕亚洲一区二区va在线| 激情欧美日韩一区| 国产96在线亚洲| 久久精品五月| 国产一区福利| www.51av欧美视频| 日韩免费看片| 中文字幕在线视频久| 久久精品一本| 日本激情一区| 欧洲av不卡| 午夜国产精品视频| 久久亚洲色图| 热久久久久久| 国产精品亚洲综合在线观看| 国产伦乱精品| 国产一区丝袜| 亚洲黄色免费看| 欧美一区二区三区高清视频| 欧美日韩精品免费观看视频完整| 岛国精品一区| 欧美/亚洲一区| 欧美一区二区三区高清视频| 91久久中文| 日韩av黄色在线| 久久精品系列| 99久久九九| 日韩中文字幕av电影| 日本亚洲最大的色成网站www| 日韩二区三区在线观看| 国产精品久久亚洲不卡| 美女视频黄免费的久久| 五月激情久久| 免费久久99精品国产| 欧美视频久久| 韩国久久久久久| 美女被久久久| 日韩精彩视频在线观看| 久久精品一区二区国产| 日韩大片在线播放| 午夜欧美精品| 日韩精品视频网| 精品国产美女a久久9999| 亚洲激情社区| 18国产精品| 蜜桃视频在线网站| 久久午夜精品| 久久一区精品| 99热精品在线| 国产精品久久乐| 亚洲第一区色| 国产精品夜夜夜| 在线日韩视频| 日本午夜精品| 99精品网站| 国产欧美一区二区三区国产幕精品 | 国产精品亚洲综合在线观看| 中文av在线全新| 亚洲乱码久久| 日韩精品诱惑一区?区三区| 在线看片一区| 日韩精品影视| 国产欧美高清| 一本色道久久精品| 精品一区二区三区视频在线播放| 性欧美xxxx免费岛国不卡电影| 四虎精品一区二区免费| 成人在线视频中文字幕| 亚洲色图网站| 国产v综合v| 国产乱码精品一区二区亚洲| 亚洲激情欧美| 国产一区二区三区免费在线| 中国女人久久久| 9999国产精品| 日韩av二区在线播放| 色婷婷狠狠五月综合天色拍| 日韩高清一区二区| 91精品蜜臀一区二区三区在线| 日本va欧美va瓶| 一区二区三区四区在线看| 国产极品嫩模在线观看91精品| 久久亚洲图片| 另类中文字幕国产精品| 国产美女亚洲精品7777| 免费人成在线不卡| 久久中文字幕av| 国产一区一一区高清不卡| 日本欧美一区| 免费在线观看视频一区| 国产亚洲一区二区手机在线观看 | 婷婷成人基地| 国产成人久久精品麻豆二区 | 裤袜国产欧美精品一区| 97精品97| 国产一区二区三区天码| 亚洲日本在线观看视频| 偷拍欧美精品| sm捆绑调教国产免费网站在线观看 | 精品中文在线| 欧美亚洲一区二区三区| 免费精品视频在线| 亚洲免费成人| 久久国产精品成人免费观看的软件| 久久三级毛片| 国产精品宾馆| 国产精品一站二站| 日韩不卡在线观看日韩不卡视频| 奶水喷射视频一区| 激情欧美日韩一区| 亚洲欧洲美洲av| 狠狠久久伊人| 老司机精品视频网| 免费看一区二区三区| 日韩高清一区| 日本成人在线视频网站| 日韩精品一区二区三区中文| 综合激情一区| 免费成人在线观看| 视频一区视频二区中文字幕| 一本一本久久| 欧美综合国产| 一二三区精品| 亚洲三级在线| 色8久久久久| 欧美一级二级三级视频| 国产一区二区三区精品在线观看| 久久国产婷婷国产香蕉| 欧美精品中文| 国产欧美69| 国产精品v日韩精品v欧美精品网站 | 九九九精品视频| 国产成人精品免费视| 精品视频国内| 在线一区av| 精品一区亚洲| 欧美日韩日本国产亚洲在线| 国产精品婷婷| 日韩一区二区免费看| 国产精品日本欧美一区二区三区| 久久成人国产| 日韩视频一二区| 91麻豆精品| 精品免费视频| 久久精品青草| 国产模特精品视频久久久久| 日本亚洲三级在线| 国产精品三p一区二区| 国产一区二区三区黄网站| 成人va天堂| 日韩精品一二区| 久久狠狠亚洲综合| 久久麻豆视频| 日韩伦理福利| 亚洲视频www| 欧美日韩a区| 色一区二区三区| 三级亚洲高清视频| 国产欧美一区二区三区精品观看| 精品福利久久久| 欧美日韩精品一区二区视频| 天堂va在线高清一区| 国产精品igao视频网网址不卡日韩 | 亚洲欧美网站在线观看| 久久精品72免费观看| 精品国产a一区二区三区v免费| 亚洲爱爱视频| 蜜臀av一区二区在线免费观看 | 日本成人中文字幕在线视频| 另类综合日韩欧美亚洲| 久久国产影院| 日韩精品亚洲专区| 久久一区国产| 在线综合亚洲| 美女久久久久久| 国产91久久精品一区二区| 美女精品在线| 红杏一区二区三区| 国产精品美女久久久| 国产精品手机在线播放| 欧美午夜精彩| 国产调教一区二区三区| 国产传媒av在线| 在线观看视频免费一区二区三区| 麻豆久久一区二区| 国产亚洲欧洲| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 国产白浆在线免费观看| 1024精品一区二区三区| 日韩精品免费一区二区夜夜嗨 | 国产精品tv| 欧美特黄一级| 久久一区精品| 一区二区国产在线| 欧产日产国产精品视频| 视频在线观看一区二区三区| 国产一区二区三区不卡视频网站 | 在线国产日韩| 日韩精品麻豆|