摘要:并行和串行任務在里面異步是一個很重要的知識點的異步跟其他語言不一樣他是根據執(zhí)行回調的方式來實現的。在之前,執(zhí)行任務想要實現這個流程控制只能通過依賴來實現或者通過而在之后官方自己實現了和來實現。
JavaScript 并行和串行任務
在 JavaScript 里面 異步 是一個很重要的知識點,JS 的異步跟其他語言不一樣, 他是根據執(zhí)行回調的方式來 實現的。由于我們不知道異步什么時候會執(zhí)行完,讓一組異步任務順序執(zhí)行就顯得很重要了,這個時候我們就需要 流程控制 ,這種流程控制有兩種 串行(series) 和 并行(parallel)
實際開發(fā)中也許你在 JS 中很少接觸到這個 并行 和 串行 ,但是如果你接觸過 gulp 我相信你應該對這個概念并不陌生.因為在 gulp 里面編寫 task 到處充斥著這種異步執(zhí)行。在 gulp(4.0)之前,執(zhí)行任務想要實現這個流程控制只能通過 依賴 來實現或者通過 run-sequence,而在 gulp(4.0)之后官方自己實現了 gulp.series 和 gulp.parallel 來實現。如果之前沒有接觸過 gulp 有興趣的可以了解下(雖然現在是 Webpack 的世界~~~)
而如果對于 串行 和 并行 有所接觸的話,一般都會使用一個叫 nimble,但是我個人對于這個庫里面實現 并行 功能是有疑問的.疑問點在于他不是按照我想象的工作方式工作
串行的簡單實現串行的實現有點像 Koa 里面對于中間件的實現。通過一個 next 函數來觸發(fā)下一個函數的執(zhí)行。
// 或者使用reduce let series = function(arr) { let index = 0; let next = function() { if (index >= arr.length) { return; } arr[index](next); index++; }; next(); };
這是一個基本的實現邏輯,實現的方式有點粗糙,其實我們每次取出的函數的方式可以進行一個優(yōu)化,不需要中間變量 index 來記錄當前的執(zhí)行函數,而是通過 Array.prototype.shift 去取數組里面的函數用來執(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(); }); } ]);并行的簡單實現
剛剛在上面提到過,我對于 nimble 中 并行的實現是有疑問的,他并沒有按照我上面的 圖片執(zhí)行,少了我覺得很重要的一步 并行應該又一個最終的函數,這個函數要等其他函數執(zhí)行完畢才會執(zhí)行
假設我有三個需要并行執(zhí)行的函數 fn1,fn2,fn3。 當這三個函數執(zhí)行之后應該需要在時間最晚的函數內執(zhí)行一個最終的函數,來 處理一些依賴邏輯。下面是我個人的 簡單實現代碼
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函數追加參數,可以使用bind函數實現,這里使用了柯里化 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); } );關于其他
以上就是簡單的 串行 和 并行 實現的基本方案, 有一些地方用到了 ES6,希望讀者不要介意。其實如果你是 面向ES6開發(fā) 的話。更簡單的方式是用 Promise 的方案,甚至可以使用 async/await 或 generator 這些高級方法,來使 異步 代碼跟同步一樣使用,使代碼的可讀性更高
// 并行 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); });
這樣看起來是不是很簡潔
ES6 大法好?。。?/b> ES6 大法好?。。?/b> ES6 大法好?。?!重要事情說三遍
相信你看出來了吧,這篇文章其實是來宣傳ES6的,不過還是希望大家能了解一下底層的實現。另外有一篇 Promise的實現。寫的相當好,極力推薦閱讀一下
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/107422.html
摘要:如果任何函數發(fā)生錯誤,會立刻執(zhí)行回調函數,并返回錯誤信息若沒有發(fā)生錯誤,則會再所有函數執(zhí)行完畢之后用回掉函數將結果返回。 Async的簡單介紹: Async是一個流程控制工具包,提供了直接而強大的異步功能?;贘avascript為Node.js設計,同時也可以直接在瀏覽器中使用。Async提供了大約20個函數,包括常用的map, reduce, filter, forEach等,異步...
摘要:阿姆達爾定律定律是計算機科學中非常重要的定律。它定義了串行系統(tǒng)并行化后的加速比的計算公式和理論上線。需要從根本上修改程序的串行行為,提高系統(tǒng)內可并行化的模塊比重,在此基礎上,合理增加并行處理器數量,才能以最小的投入,得到最大的加速比。 有關為什么要使用并行程序的問題前面已經進行了簡單的探討。總的來說,最重要的應該是處于兩個目的。 第一,為了獲得更好的性能; 第二,由于業(yè)務模型的需要,確...
閱讀 2959·2019-08-30 15:55
閱讀 2075·2019-08-30 14:02
閱讀 1362·2019-08-29 15:23
閱讀 1070·2019-08-29 11:27
閱讀 536·2019-08-26 11:43
閱讀 3245·2019-08-26 10:32
閱讀 1300·2019-08-23 14:41
閱讀 3352·2019-08-23 14:41