摘要:因為瀏覽器環(huán)境里是單線程的,所以異步編程在前端領(lǐng)域尤為重要。除此之外,它還有兩個特性,使它可以作為異步編程的完整解決方案函數(shù)體內(nèi)外的數(shù)據(jù)交換和錯誤處理機(jī)制。
在我們?nèi)粘>幋a中,需要異步的場景很多,比如讀取文件內(nèi)容、獲取遠(yuǎn)程數(shù)據(jù)、發(fā)送數(shù)據(jù)到服務(wù)端等。因為瀏覽器環(huán)境里Javascript是單線程的,所以異步編程在前端領(lǐng)域尤為重要。
異步的概念所謂異步,是指當(dāng)一個過程調(diào)用發(fā)出后,調(diào)用者不能立刻得到結(jié)果。實際處理這個調(diào)用的過程在完成后,通過狀態(tài)、通知或者回調(diào)來通知調(diào)用者。
比如我們寫這篇文字時點擊發(fā)布按鈕,我們并不能馬上得到文章發(fā)布成功或者失敗。等待服務(wù)器處理,這段時間我們可以做其他的事情,當(dāng)服務(wù)器處理完成后,通知我們是否發(fā)布成功。
所謂同步,是指當(dāng)一個過程調(diào)用發(fā)出后,必須等待這個過程處理完成后,再處理其他事情。即堵塞執(zhí)行。
異步的方式在es6之前,我們實現(xiàn)異步有4種方法,回調(diào)、事件、發(fā)布訂閱和promise方式。
異步之回調(diào):function dealTask(param, callback) { // Deal with some time consuming tasks. // ... Object.prototype.toString.call(callback) === "[object Function]" ? callback() : null; } dealTask({ id: 1 }, function() { console.log("... I am in the callback..."); })
回調(diào)的方式來實現(xiàn)異步其實就是把需要在當(dāng)前任務(wù)完成后執(zhí)行的函數(shù)當(dāng)成參數(shù)傳入,完成任務(wù)后執(zhí)行即可。
異步之事件function dealTask(param) { // Deal with some time consuming tasks. // ... events.trigger("dealTaskFinish") } events.on("dealTaskFinish", function() { console.log("...I am in the end..."); })
通過事件來實現(xiàn)回調(diào),好處是方便實用,跨模塊傳遞數(shù)據(jù)。壞處是,事件用的多了后業(yè)務(wù)邏輯混亂,不知道哪里注冊過哪里監(jiān)聽過。
另外需要注意的是在web component場景下,mount后注冊過的事件需要在unmount釋放,不然會導(dǎo)致內(nèi)存泄露。
異步之發(fā)布訂閱發(fā)布訂閱的簡單例子是,一個開關(guān),同時并聯(lián)幾個燈泡(在不同房間),觸發(fā)的時候,幾個燈泡都會得到指令,然后執(zhí)行發(fā)光的行為。
// 使用pubsubz實現(xiàn) var testSubscriber = function(data ){ console.log(data ); }; var testSubscription = pubsubz.subscribe( "example", testSubscriber ); pubsubz.publish( "example", "hello" );
訂閱發(fā)布與的性質(zhì)與"事件監(jiān)聽"類似,不同的是,我們可以通過查看"消息中心",了解存在多少信號、每個信號有多少訂閱者,從而監(jiān)控程序的運行。
異步之Promisefunction helloWorld (ready) { return new Promise(function (resolve, reject) { if (ready) { resolve("Hello World!") } else { reject("Good bye!") } }) } helloWorld(true).then(function (message) { console.log(message) }, function (error) { console.log(error) })
Promises對象是CommonJS工作組提出的一種規(guī)范,是對異步編程的一種統(tǒng)一,其實也就是語法糖,可閱讀性變強(qiáng)了而已。
在ES6出來以后,我們的異步方式也發(fā)生了改變。
異步之GeneratorGenerator函數(shù)是協(xié)程在ES6的實現(xiàn),最大特點就是可以交出函數(shù)的執(zhí)行權(quán)(即暫停執(zhí)行)。
Generator函數(shù)可以暫停執(zhí)行和恢復(fù)執(zhí)行,這是它能封裝異步任務(wù)的根本原因。除此之外,它還有兩個特性,使它可以作為異步編程的完整解決方案:函數(shù)體內(nèi)外的數(shù)據(jù)交換和錯誤處理機(jī)制。
function* Foo(x) { yield x + 1; var y = yield null; return x + y; } var foo = Foo(5); foo.next(); // { value: 6, done: false } foo.next(); // { value: null, done: false } foo.next(8); // { value: 13, done: true }
next方法返回值的value屬性,是Generator函數(shù)向外輸出數(shù)據(jù);next方法還可以接受參數(shù),這是向Generator函數(shù)體內(nèi)輸入數(shù)據(jù)。
yield命令用于將程序的執(zhí)行權(quán)移出Generator函數(shù),那么就需要一種方法,將執(zhí)行權(quán)再交還給Generator函數(shù)
上面的方式,是我們手動調(diào)用Generator函數(shù)執(zhí)行,但是當(dāng)我們的需要執(zhí)行next方法很多時,就需要Generator函數(shù)自動執(zhí)行了。
Generator函數(shù)自動執(zhí)行的意思是,通過一定的方法來自動執(zhí)行next方法,比如:
function autoRunGen(gen){ var g = gen(); function next(data){ var result = g.next(data); if (result.done) return result.value; result.value.then(function(data){ next(data); }); } next(); }
co模塊是TJ開發(fā)的一個小工具,用于Generator函數(shù)的自動執(zhí)行。他的主要思想和上面的代碼片段類似。
使用co的前提條件是,Generator函數(shù)的yield命令后面,只能是Promise對象。
co(function *() { var data = yield $.get("/api/data"); console.log(data); var user = yield $.get("/api/user"); console.log(user); var products = yield $.get("/api/products"); console.log(products); });
co模塊使得我們可以像寫同步代碼一樣,寫異步代碼。
異步之a(chǎn)sync/awaitasync函數(shù)僅僅是Generator函數(shù)的語法糖。
var fs = require("fs"); var readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error) reject(error); resolve(data); }); }); }; var gen = function* (){ var f1 = yield readFile("/etc/a.js"); var f2 = yield readFile("/etc/b.js"); console.log(f1.toString()); console.log(f2.toString()); };
使用async/await方式:
var asyncReadFile = async function (){ var f1 = await readFile("/etc/a.js"); var f2 = await readFile("/etc/b.js"); console.log(f1.toString()); console.log(f2.toString()); };
async函數(shù)就是將Generator函數(shù)的星號(*)替換成async,將yield替換成await,僅此而已。
不同的是,Generator執(zhí)行需要手動執(zhí)行,而async函數(shù)可以自動執(zhí)行,像寫同步一樣寫異步。Generator返回Iterator對象,async函數(shù)返回Promise對象。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/90894.html
摘要:模塊化編程,已經(jīng)成為一個迫切的需求。隨著網(wǎng)站功能逐漸豐富,網(wǎng)頁中的也變得越來越復(fù)雜和臃腫,原有通過標(biāo)簽來導(dǎo)入一個個的文件這種方式已經(jīng)不能滿足現(xiàn)在互聯(lián)網(wǎng)開發(fā)模式,我們需要團(tuán)隊協(xié)作模塊復(fù)用單元測試等等一系列復(fù)雜的需求。 隨著網(wǎng)站逐漸變成互聯(lián)網(wǎng)應(yīng)用程序,嵌入網(wǎng)頁的Javascript代碼越來越龐大,越來越復(fù)雜。網(wǎng)頁越來越像桌面程序,需要一個團(tuán)隊分工協(xié)作、進(jìn)度管理、單元測試等等......開發(fā)...
摘要:這就是積極的函數(shù)式編程。上一章翻譯連載第章遞歸下輕量級函數(shù)式編程你不知道的姊妹篇原創(chuàng)新書移動前端高效開發(fā)實戰(zhàn)已在亞馬遜京東當(dāng)當(dāng)開售。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅實的梁柱;分享,是 CSS 里最閃耀的一瞥;總...
摘要:最后,提供個正確使用的場景。異步編程的一個很好的用例就請求。這意味著異步函數(shù)只能解決一小部分語言單線程中的局限性問題。中有類似的集群子進(jìn)程概念,他們也是多線程但是和還是有區(qū)別。可用的特性由于的多線程特性,工作者只能訪問特性的一個子集。 showImg(https://segmentfault.com/img/bVblS8J?w=400&h=298); 這是專門探索 JavaScript...
摘要:而納入規(guī)范的也是建立在基礎(chǔ)上的。繼續(xù)閱讀的相關(guān)解釋語法其中函數(shù)擁有兩個參數(shù)和。可以看到,在語法上看,還是有點像回調(diào)函數(shù)那種形式的,囧。完成操作已經(jīng)成功執(zhí)行完畢。消費,即對的所代表的值進(jìn)行一系列的處理。 文 | Leigh,UPYUN 已獲得授權(quán)原文鏈接:http://t.cn/R403hc4 在 JavaScript 這么多年發(fā)展中,尤其在前端領(lǐng)域框架層出不窮,解決方案也琳瑯滿目,Pr...
摘要:意味著代指的操作由于某些原因失敗。第一步構(gòu)造函數(shù)有三種狀態(tài),。這個構(gòu)造函數(shù)我們可以先這樣寫創(chuàng)建一個時,首先進(jìn)行狀態(tài)初始化。所有的都是的,而并不是所有的對象都是。 一、JavaScript異步編程背景 ? 從去年ES2015發(fā)布至今,已經(jīng)過去了一年多,ES2015發(fā)布的新的語言特性中最為流行的也就莫過于Promise了,Promise使得如今JavaScript異步編程如此輕松愜意...
閱讀 2831·2023-04-26 02:23
閱讀 1570·2021-11-11 16:55
閱讀 3149·2021-10-19 11:47
閱讀 3352·2021-09-22 15:15
閱讀 1975·2019-08-30 15:55
閱讀 1033·2019-08-29 15:43
閱讀 1288·2019-08-29 13:16
閱讀 2188·2019-08-29 12:38