摘要:而這樣一層一層嵌套進去的作用就是一個執(zhí)行完了,執(zhí)行下一個。函數的參數和函數一樣,只不過是執(zhí)行的順序與函數相反,是倒過來執(zhí)行的。第二個方案,也是他給我的思路。
這篇文章的起源是這樣一段代碼
這段代碼的作用很簡單,就是讓一系列的動畫,按順序執(zhí)行。而這樣一層一層嵌套進去的作用就是一個執(zhí)行完了,執(zhí)行下一個。
為了解決這個問題我就想到了是不是可以把這些事件放到一個數組里,然后依次執(zhí)行呢?也就是說實現(xiàn)一個seq(tasks,finally)函數
/** * @param {function []} tasks - function array * @param {function} cb - 執(zhí)行完的回調 */ function seq(tasks, cb) { }
我的思路是每次執(zhí)行完一個function之后再執(zhí)行下一個函數,如果執(zhí)行到最后一個函數就執(zhí)行最后的cb即
function seq(tasks, cb) { (function runTask(i) { var task = tasks[i]; task(function() { i++; if (i !== tasks.length) { runTask(i); } else { cb(); } }); })(0); }
但是顯然這么實現(xiàn)并不優(yōu)雅(Zhuāng Bī),那么有沒有更優(yōu)雅的方案呢?顯然是有的。我們可以使用ES5的reduceRight函數(MSDN文檔)
如果你并不知道這個函數的話,我們就要從和它差不多的reduce函數(MSDN文檔)說起了。
reduce函數接收兩個參數callback、initialValue
callback
執(zhí)行數組中每個值的函數,包含四個參數
previousValue
上一次調用回調返回的值,或者是提供的初始值(initialValue)
currentValue
數組中當前被處理的元素
index
當前元素在數組中的索引
array
調用 reduce 的數組
initialValue
作為第一次調用 callback 的第一個參數。
/** @examples **/ var array = [ { id: 1, name: "小李" }, { id: 2, name: "小張" }, { id: 3, name: "小劉" }, { id: 4, name: "小王" } ] var objMap = array.reduce(function(map,nowObj,index,array) { map[nowObj.id] = nowObj; return map; },{});
很簡單的就把一個array,轉成了一個以id為key,obj為value的ObjMap有木有?就是這么簡單。
reduceRight函數的參數和reduce函數一樣,只不過是執(zhí)行的順序與reduce函數相反,是倒過來執(zhí)行的。這樣的話我們就可以把上面那個tasks轉換成類似最一開始那張圖一樣的結構。
function seq2(tasks, cb) { tasks.reduceRight(function(cb, task) { return function() { return task(cb); }; }, cb)(); } //這段代碼的推導如下 //第一次執(zhí)行 function() { return task5(cb); }; //第二次執(zhí)行 function() { return task4(function() { return task5(cb); }); } //第三次執(zhí)行 function() { return task3(function() { return task4(function() { return task5(cb); }); }); }; //第四次執(zhí)行 function() { return task2(function() { return task3(function() { return task4(function() { return task5(cb); }); }); }) }; //最后一次執(zhí)行 function() { return task1(function() { return task2(function() { return task3(function() { return task4(function() { return task5(cb); }); }); }); }); };
這樣就得到了一個跟上面最一開始那張圖一模一樣的一個function,然后最重要的是reduceRight面那個(),他就是啟動這個最終返回function的開關。
測試用例如下:
var tasks = [1, 2, 3, 4, 5]; tasks = tasks.map(function(i) { return function(cb) { setTimeout(function() { console.log(i); cb(); }, Math.random() * 500 | 0); } }); seq(tasks, function() { console.log("all Done"); }); seq2(tasks, function() { console.log("all Done"); });
這個問題是我公司的一位同事(老師)給我出的題目。第二個方案,也是他給我的思路。感謝我的這位老師,雖然在工作中我說的不多,但是在我內心里,我對您的崇拜那是簡直了。哈哈。最后是github源代碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/79611.html
摘要:并行和串行任務在里面異步是一個很重要的知識點的異步跟其他語言不一樣他是根據執(zhí)行回調的方式來實現(xiàn)的。在之前,執(zhí)行任務想要實現(xiàn)這個流程控制只能通過依賴來實現(xiàn)或者通過而在之后官方自己實現(xiàn)了和來實現(xiàn)。 JavaScript 并行和串行任務 在 JavaScript 里面 異步 是一個很重要的知識點,JS 的異步跟其他語言不一樣, 他是根據執(zhí)行回調的方式來 實現(xiàn)的。由于我們不知道異步什么時候會...
摘要:相關環(huán)境由于是一個幾年前的項目,所以使用的是這樣的。一些小提示本次優(yōu)化筆記,并不會有什么文件的展示。將異步改為了串行,喪失了作為異步事件流的優(yōu)勢。 這兩天針對一個Node項目進行了一波代碼層面的優(yōu)化,從響應時間上看,是一次很顯著的提升。 一個純粹給客戶端提供接口的服務,沒有涉及到頁面渲染相關。 背景 首先這個項目是一個幾年前的項目了,期間一直在新增需求,導致代碼邏輯變得也比較復雜,接...
摘要:所以這里需要另外的操作來對文件加載進行優(yōu)化加載這是中定義的一個屬性,它用來表示的是,當渲染引擎遇到的時候,如果引用的是外部資源,則會暫時掛起,并進行加載。 在js引擎部分,我們可以了解到,當渲染引擎解析到script標簽時,會將控制權給JS引擎,如果script加載的是外部資源,則需要等待下載完后才能執(zhí)行。 所以,在這里,我們可以對其進行很多優(yōu)化工作。 放置在body底部 為了讓渲染引...
摘要:前同事留下的測試,是基于瀏覽器的,主要還是功能測試。這里不詳細說怎么在瀏覽器端使用測試了。而且作者也是建議和支持這樣做的,簡單明了的測試腳本,重要性有時候可能和測試本身一樣重要。經測試,在瀏覽器也有這種問題。 2016-09-03 更新 隨著在工作學習中更多地接觸、使用測試工具,發(fā)現(xiàn)自己在本文中的一些記錄是不準確、不正確的。 今天(九月三日)在家看了 NingJs 的直播,其中有一個分...
閱讀 1383·2021-11-22 13:54
閱讀 1578·2021-11-22 09:34
閱讀 2903·2021-11-22 09:34
閱讀 4261·2021-10-13 09:39
閱讀 3426·2019-08-26 11:52
閱讀 3438·2019-08-26 11:50
閱讀 1631·2019-08-26 10:56
閱讀 2024·2019-08-26 10:44