摘要:并行和串行任务在里面异步是一个很重要的知识点的异步跟其他语言不一样他是根据执行回调的方式来实现的。在之前,执行任务想要实现这个流程控制只能通过依赖来实现或者通过而在之后官方自己实现了和来实现。
JavaScript 并行和串行任务
在 JavaScript 里面 异步 是一个很重要的知识点,JS 的异步跟其他语言不一样, 他是根据执行回调的方式来 实现的。由于我们不知道异步什么时候会执行完,让一组异步任务顺序执行就显得很重要了,这个时候我们就需要 流程控制 ,这种流程控制有两种 串行(series) 和 并行(parallel)
实际开发中也许你在 JS 中很少接触到这个 并行 和 串行 ,但是如果你接触过 gulp 我相信你应该对这个概念并不陌生.因为在 gulp 里面编写 task 到处充斥着这种异步执行。在 gulp(4.0)之前,执行任务想要实现这个流程控制只能通过 依赖 来实现或者通过 run-sequence,而在 gulp(4.0)之后官方自己实现了 gulp.series 和 gulp.parallel 来实现。如果之前没有接触过 gulp 有兴趣的可以了解下(虽然现在是 Webpack 的世界~~~)
而如果对于 串行 和 并行 有所接触的话,一般都会使用一个叫 nimble,但是我个人对于这个库里面实现 并行 功能是有疑问的.疑问点在于他不是按照我想象的工作方式工作
串行的简单实现串行的实现有点像 Koa 里面对于中间件的实现。通过一个 next 函数来触发下一个函数的执行。
// 或者使用reduce let series = function(arr) { let index = 0; let next = function() { if (index >= arr.length) { return; } arr[index](next); index++; }; next(); };
这是一个基本的实现逻辑,实现的方式有点粗糙,其实我们每次取出的函数的方式可以进行一个优化,不需要中间变量 index 来记录当前的执行函数,而是通过 Array.prototype.shift 去取数组里面的函数用来执行
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 中 并行的实现是有疑问的,他并没有按照我上面的 图片执行,少了我觉得很重要的一步 并行应该又一个最终的函数,这个函数要等其他函数执行完毕才会执行
假设我有三个需要并行执行的函数 fn1,fn2,fn3。 当这三个函数执行之后应该需要在时间最晚的函数内执行一个最终的函数,来 处理一些依赖逻辑。下面是我个人的 简单实现代码
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开发 的话。更简单的方式是用 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 大法好!!! ES6 大法好!!! ES6 大法好!!!重要事情说三遍
相信你看出来了吧,这篇文章其实是来宣传ES6的,不过还是希望大家能了解一下底层的实现。另外有一篇 Promise的实现。写的相当好,极力推荐阅读一下
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/107422.html
摘要:如果任何函数发生错误,会立刻执行回调函数,并返回错误信息若没有发生错误,则会再所有函数执行完毕之后用回掉函数将结果返回。 Async的简单介绍: Async是一个流程控制工具包,提供了直接而强大的异步功能。基于Javascript为Node.js设计,同时也可以直接在浏览器中使用。Async提供了大约20个函数,包括常用的map, reduce, filter, forEach等,异步...
摘要:阿姆达尔定律定律是计算机科学中非常重要的定律。它定义了串行系统并行化后的加速比的计算公式和理论上线。需要从根本上修改程序的串行行为,提高系统内可并行化的模块比重,在此基础上,合理增加并行处理器数量,才能以最小的投入,得到最大的加速比。 有关为什么要使用并行程序的问题前面已经进行了简单的探讨。总的来说,最重要的应该是处于两个目的。 第一,为了获得更好的性能; 第二,由于业务模型的需要,确...
阅读 2878·2019-08-30 15:55
阅读 1948·2019-08-30 14:02
阅读 1184·2019-08-29 15:23
阅读 978·2019-08-29 11:27
阅读 427·2019-08-26 11:43
阅读 3160·2019-08-26 10:32
阅读 1211·2019-08-23 14:41
阅读 3275·2019-08-23 14:41