摘要:并行和串行任務(wù)在里面異步是一個(gè)很重要的知識(shí)點(diǎn)的異步跟其他語(yǔ)言不一樣他是根據(jù)執(zhí)行回調(diào)的方式來(lái)實(shí)現(xiàn)的。在之前,執(zhí)行任務(wù)想要實(shí)現(xiàn)這個(gè)流程控制只能通過(guò)依賴來(lái)實(shí)現(xiàn)或者通過(guò)而在之后官方自己實(shí)現(xiàn)了和來(lái)實(shí)現(xiàn)。
JavaScript 并行和串行任務(wù)
在 JavaScript 里面 異步 是一個(gè)很重要的知識(shí)點(diǎn),JS 的異步跟其他語(yǔ)言不一樣, 他是根據(jù)執(zhí)行回調(diào)的方式來(lái) 實(shí)現(xiàn)的。由于我們不知道異步什么時(shí)候會(huì)執(zhí)行完,讓一組異步任務(wù)順序執(zhí)行就顯得很重要了,這個(gè)時(shí)候我們就需要 流程控制 ,這種流程控制有兩種 串行(series) 和 并行(parallel)
實(shí)際開(kāi)發(fā)中也許你在 JS 中很少接觸到這個(gè) 并行 和 串行 ,但是如果你接觸過(guò) gulp 我相信你應(yīng)該對(duì)這個(gè)概念并不陌生.因?yàn)樵?gulp 里面編寫(xiě) task 到處充斥著這種異步執(zhí)行。在 gulp(4.0)之前,執(zhí)行任務(wù)想要實(shí)現(xiàn)這個(gè)流程控制只能通過(guò) 依賴 來(lái)實(shí)現(xiàn)或者通過(guò) run-sequence,而在 gulp(4.0)之后官方自己實(shí)現(xiàn)了 gulp.series 和 gulp.parallel 來(lái)實(shí)現(xiàn)。如果之前沒(méi)有接觸過(guò) gulp 有興趣的可以了解下(雖然現(xiàn)在是 Webpack 的世界~~~)
而如果對(duì)于 串行 和 并行 有所接觸的話,一般都會(huì)使用一個(gè)叫 nimble,但是我個(gè)人對(duì)于這個(gè)庫(kù)里面實(shí)現(xiàn) 并行 功能是有疑問(wèn)的.疑問(wèn)點(diǎn)在于他不是按照我想象的工作方式工作
串行的簡(jiǎn)單實(shí)現(xiàn)串行的實(shí)現(xiàn)有點(diǎn)像 Koa 里面對(duì)于中間件的實(shí)現(xiàn)。通過(guò)一個(gè) next 函數(shù)來(lái)觸發(fā)下一個(gè)函數(shù)的執(zhí)行。
// 或者使用reduce let series = function(arr) { let index = 0; let next = function() { if (index >= arr.length) { return; } arr[index](next); index++; }; next(); };
這是一個(gè)基本的實(shí)現(xiàn)邏輯,實(shí)現(xiàn)的方式有點(diǎn)粗糙,其實(shí)我們每次取出的函數(shù)的方式可以進(jìn)行一個(gè)優(yōu)化,不需要中間變量 index 來(lái)記錄當(dāng)前的執(zhí)行函數(shù),而是通過(guò) Array.prototype.shift 去取數(shù)組里面的函數(shù)用來(lái)執(zhí)行
let series = function(arr) { let next = function(data) { let fn = arr.shift(); if (!fn) { return; } fn(next,data); }; next(); }; // 使用方法 let str = ""; series([ function(next) { setTimeout(function() { str = "Hello" next(str); }, 100); }, function(next,data) { setTimeout(function() { str += "World" console.log(str) console.log(data); next(); }); } ]);并行的簡(jiǎn)單實(shí)現(xiàn)
剛剛在上面提到過(guò),我對(duì)于 nimble 中 并行的實(shí)現(xiàn)是有疑問(wèn)的,他并沒(méi)有按照我上面的 圖片執(zhí)行,少了我覺(jué)得很重要的一步 并行應(yīng)該又一個(gè)最終的函數(shù),這個(gè)函數(shù)要等其他函數(shù)執(zhí)行完畢才會(huì)執(zhí)行
假設(shè)我有三個(gè)需要并行執(zhí)行的函數(shù) fn1,fn2,fn3。 當(dāng)這三個(gè)函數(shù)執(zhí)行之后應(yīng)該需要在時(shí)間最晚的函數(shù)內(nèi)執(zhí)行一個(gè)最終的函數(shù),來(lái) 處理一些依賴邏輯。下面是我個(gè)人的 簡(jiǎn)單實(shí)現(xiàn)代碼
let parallel = function(arr, finnaly) { let fn, index = 0; let statusArr = Array(arr.length) .fill() .map(() => ({ isActive: false, data: null })); let isFinished = function() { return statusArr.every(item => { return item.isActive === true; }); }; let resolve = function(index) { return function(data) { statusArr[index].data = data; statusArr[index].isActive = true; let isFinish = isFinished(); if (isFinish) { let datas = statusArr.map(item => { return item.data; }); finnaly(datas); } }; }; while ((fn = arr.shift())) { // 給resolve函數(shù)追加參數(shù),可以使用bind函數(shù)實(shí)現(xiàn),這里使用了柯里化 fn(resolve(index)); index++; } }; // 使用方法 let str = ""; parallel( [ function(resolve) { setTimeout(function() { str = "Hello"; resolve("Hello"); }, 1000); }, function(resolve) { setTimeout(function() { str += "World"; resolve("World"); }, 20); } ], function(datas) { console.log("finily", datas); } );關(guān)于其他
以上就是簡(jiǎn)單的 串行 和 并行 實(shí)現(xiàn)的基本方案, 有一些地方用到了 ES6,希望讀者不要介意。其實(shí)如果你是 面向ES6開(kāi)發(fā) 的話。更簡(jiǎn)單的方式是用 Promise 的方案,甚至可以使用 async/await 或 generator 這些高級(jí)方法,來(lái)使 異步 代碼跟同步一樣使用,使代碼的可讀性更高
// 并行 let datas = await Promise.all([ new Promise(resolve => { setTimeout(resolve.bind(this,10), 1000); }), new Promise(resolve => { setTimeout(resolve.bind(this,12), 2000); }) ]) // 串行 let data1 = await new Promise(resolve => { setTimeout(resolve.bind(this, 10), 1000); }) let data2 = await new Promise(resolve => { setTimeout(resolve.bind(this, 12), 1000); });
這樣看起來(lái)是不是很簡(jiǎn)潔
ES6 大法好!!! ES6 大法好!!! ES6 大法好!!!重要事情說(shuō)三遍
相信你看出來(lái)了吧,這篇文章其實(shí)是來(lái)宣傳ES6的,不過(guò)還是希望大家能了解一下底層的實(shí)現(xiàn)。另外有一篇 Promise的實(shí)現(xiàn)。寫(xiě)的相當(dāng)好,極力推薦閱讀一下
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/107422.html
摘要:回調(diào)函數(shù)指定了下一步操作。異步操作的流程控制參數(shù)為秒后返回結(jié)果上面代碼的函數(shù)是一個(gè)異步任務(wù),非常耗時(shí),每次執(zhí)行需要秒才能完成,然后再調(diào)用回調(diào)函數(shù)。 單線程模型同步任務(wù)和異步任務(wù)任務(wù)隊(duì)列和事件循環(huán)異步操作的模式回調(diào)函數(shù)事件監(jiān)聽(tīng)發(fā)布/訂閱異步操作的流程控制串行執(zhí)行并行執(zhí)行并行與串行的結(jié)合 1.單線程模型指的是js只在線程運(yùn)行,一個(gè)時(shí)間執(zhí)行一個(gè)任務(wù),其他任務(wù)排隊(duì)。事實(shí)上是一個(gè)運(yùn)行腳本的主線程...
摘要:完成請(qǐng)問(wèn)應(yīng)該如何安排操作流程上面代碼采用個(gè)回調(diào)函數(shù)的嵌套,不僅寫(xiě)起來(lái)麻煩,容易出錯(cuò),而且難以維護(hù)串行執(zhí)行我們可以編寫(xiě)一個(gè)流程控制函數(shù),讓它來(lái)控制異步任務(wù),一個(gè)任務(wù)完成以后,再執(zhí)行另一個(gè)。 前言 回調(diào)地獄showImg(https://segmentfault.com/img/remote/1460000011554165?w=1000&h=710); js異步 Javascript 語(yǔ)...
摘要:如果任何函數(shù)發(fā)生錯(cuò)誤,會(huì)立刻執(zhí)行回調(diào)函數(shù),并返回錯(cuò)誤信息若沒(méi)有發(fā)生錯(cuò)誤,則會(huì)再所有函數(shù)執(zhí)行完畢之后用回掉函數(shù)將結(jié)果返回。 Async的簡(jiǎn)單介紹: Async是一個(gè)流程控制工具包,提供了直接而強(qiáng)大的異步功能。基于Javascript為Node.js設(shè)計(jì),同時(shí)也可以直接在瀏覽器中使用。Async提供了大約20個(gè)函數(shù),包括常用的map, reduce, filter, forEach等,異步...
摘要:阿姆達(dá)爾定律定律是計(jì)算機(jī)科學(xué)中非常重要的定律。它定義了串行系統(tǒng)并行化后的加速比的計(jì)算公式和理論上線。需要從根本上修改程序的串行行為,提高系統(tǒng)內(nèi)可并行化的模塊比重,在此基礎(chǔ)上,合理增加并行處理器數(shù)量,才能以最小的投入,得到最大的加速比。 有關(guān)為什么要使用并行程序的問(wèn)題前面已經(jīng)進(jìn)行了簡(jiǎn)單的探討。總的來(lái)說(shuō),最重要的應(yīng)該是處于兩個(gè)目的。 第一,為了獲得更好的性能; 第二,由于業(yè)務(wù)模型的需要,確...
閱讀 2895·2019-08-30 15:55
閱讀 2000·2019-08-30 14:02
閱讀 1239·2019-08-29 15:23
閱讀 1006·2019-08-29 11:27
閱讀 461·2019-08-26 11:43
閱讀 3190·2019-08-26 10:32
閱讀 1253·2019-08-23 14:41
閱讀 3301·2019-08-23 14:41