摘要:基數,倒計時進入倒計時進入倒計時進入倒計時進入倒計時進入倒計時倒計數結束執行完畢,結果為,準備進入。
2018-12-21 更新
1、簡化調用方式,更貼近普通函數的風格;
精簡版戳這里!
2018-12-05 更新
1、支持頭節點入參;
2、簡化調用方式;
//源碼 function chainedFn(chain,firstFnArguments){ // 入參數據校驗 ... for(var i=0;i鏈條模板:
chainedFn([ {"fnName":方法名,"fnArg":實例化時的入參對象(非必傳)}, {"fnName":方法名,"fnArg":實例化時的入參對象(非必傳)}, {"fnName":方法名,"fnArg":實例化時的入參對象(非必傳)} ],[頭節點入參1,頭節點入參2,頭節點入參3...] );節點模板:
function 函數名(callback,鏈條上的【fnArg】(可選)){ //callback this.fnCont = function(...){ //如果是頭節點,則入參對應chainedFn的第二個參數;否則等價于上一節點的【callback】 //TODO... if(typeof callback == "function"){ callback(...); // 等價于下一個節點的【fuCont】 } } }函數示例:
假設現在有3個需要同步執行的函數:FnA,FnB,FnC;
FnA的功能:將基數(入參1),乘上乘積(入參2),結果值和倒計時(入參3)傳給FnB;
FnB的功能:進入倒計時,倒計時結束后,將入參乘上5,然后傳給fnC;
FnC的功能:將參數打印出來;// 組合鏈式關系 ... chainedFn([ {"fnName":FnA}, //規定初始值 {"fnName":FnB,"fnArg":"test"},//倒計時結束后,進行一些操作 {"fnName":FnC}//展示處理結果 ],[2,10,5] ); // FnA的功能:將入參1乘上入參2,然后執行FnB,同時設置fnB的倒計時時間(入參3)... function FnA(callback){ this.fnCont = function(base,multiplier,cDown){ console.log("【from FnA】基數:" + base + ",乘積:" + multiplier + ",倒計時:" + cDown); var num = base * multiplier ; if(typeof callback == "function"){ console.log("【from FnA】執行完畢,結果為:" + num + ",準備進入FnB。"); callback(num,cDown); // 等價于【FnB】的fuCont } } } // FnB的功能:倒計時結束后,將入參乘上5 ... function FnB(callback,fnArg){ this.fnCont = function(base,cDown){ alert(fnArg); console.log("【from FnB】基數:" + base + ",倒計時:" + cDown); var countDown = cDown; var tTout = setInterval(function(){ console.log("【from FnB】進入倒計時 -> " + --countDown + "s"); if(countDown <= 0){ console.log("【from FnB】倒計數結束"); countDown = -1; clearTimeout(tTout); var num = base * 5; if(typeof callback == "function"){ console.log("【from FnB】執行完畢,結果為:" + num + ",準備進入FnC。"); callback(num);// 等價于【FnC】的fuCont } } },1000); } }; // 將參數打印出來 ... function FnC(callback){ this.fnCont = function(tArg){ console.log("【from FnC】計算結果為:" + tArg); if(typeof callback == "function"){ callback(); } } };執行結果:
【from FnA】基數:2,乘積:10,倒計時:5 【from FnA】執行完畢,結果為:20,準備進入FnB。 【from FnB】基數:20,倒計時:5 【from FnB】進入倒計時 -> 4s 【from FnB】進入倒計時 -> 3s 【from FnB】進入倒計時 -> 2s 【from FnB】進入倒計時 -> 1s 【from FnB】進入倒計時 -> 0s 【from FnB】倒計數結束 【from FnB】執行完畢,結果為:100,準備進入FnC。 【from FnC】計算結果為:100此時突然新增一個需求:在FnA中指定一個值B,內容FnC輸出值A不可大于B:如果A超過B則取B,否則取A:
FnA增加指定參數(maxNum),并傳出:
function FnA(callback){ this.fnCont = function(base,multiplier,cDown,maxNum){ console.log("【from FnA】基數:" + base + ",乘積:" + multiplier + ",倒計時:" + cDown); var num = base * multiplier ; if(typeof callback == "function"){ console.log("【from FnA】執行完畢,結果為:" + num + ",準備進入下一節點"); callback(num,cDown,maxNum); // 等價于【FnB】的fuCont } } }FnB原封不動將值傳出:
function FnB(callback){ this.fnCont = function(base,cDown,maxNum){ console.log("【from FnB】基數:" + base + ",倒計時:" + cDown); var countDown = cDown; var tTout = setInterval(function(){ console.log("from FnB:進入倒計時 -> " + --countDown + "s"); if(countDown <= 0){ console.log("【from FnB】倒計數結束"); countDown = -1; clearTimeout(tTout); var num = base * 5; if(typeof callback == "function"){ console.log("【from FnB】執行完畢,結果為:" + num + ",準備進入下一節點"); callback(num,maxNum);// 等價于【FnC】的fuCont } } },1000); } };新增一個方法(FnD),此函接受兩個入參A,B。如果A小于B,則返回A,否則返回B:
function FnD(callback){ this.fnCont = function(num,max){ var tmpNum = num; var maxNum = max; if(tmpNum > maxNum){ tmpNum = maxNum; console.log("【from FnD】計算結果為:" + tArg); } if(typeof callback == "function"){ callback(tmpNum); } } };調整鏈式結構(指定最大值,增加FnD):
// 組合鏈式關系 ... chainedFn([ {"fnName":FnA},//規定初始值 {"fnName":FnB},//倒計時結束后,進行一些操作 {"fnName":FnD},//最大值限制 {"fnName":FnC} //展示處理結果 ],[2,10,3,50] );輸出結果:
【from FnA】基數:2,乘積:10,倒計時:3 【from FnA】執行完畢,結果為:20,準備進入下一節點 【from FnB】基數:20,倒計時:3 【from FnB】進入倒計時 -> 2s 【from FnB】進入倒計時 -> 1s 【from FnB】進入倒計時 -> 0s 【from FnB】倒計數結束 【from FnB】執行完畢,結果為:100,準備進入下一節點 【from FnD】值(100)超出限制,取限制值:50 【from FnC】計算結果為:50聊一下背景
最近在開發項目的時候,因為需要數據同步處理,所以會遇到很多涉及到函數回調的地方。最多的達到了7個!不管是自己擼代碼,還是維護代碼,基本都是一項很煩心的事,特別要改原先其他同事寫的邏輯,我寧愿重新寫。代碼都是這樣的:
a(xx,function(){ b(xx,function(){ c(xx,function(){ ..... }); }); });又或者這樣的:
function a(xx){ //..... b(); } function b(xx){ //..... c(); } ......故,抽了點時間寫了一個:以鏈式調用的形式用來處理需要回調的函數。
源碼:
/** *鏈式回調 **/ function chainedFn(chain){ // 入參數據校驗 ... for(var i=0;i鏈條模板:
chainedFn([ {"fnName":方法名A,"fnArg":實例化時的入參對象(非必傳)}, {"fnName":方法名B,"fnArg":實例化時的入參對象(非必傳)}, {"fnName":方法名C,"fnArg":實例化時的入參對象(非必傳)} ]); 說明:chainedFn的入參是JSON數組,【方法名名】需存在,且符合“對象模版”;【實例化時的入參】參數可無;方法模版:
function **方法名**(**實例化參數**,callback){ this.fnCont = function(tArg1,tArg2...){ //fnCont:函數主體(函數名不可變),tArg:被回調的入參(鏈條上一節的入參) // 函數功能代碼 ... if(typeof callback == "function"){ callback(tArg1,tArg2...);//回調的入參(鏈條下一節的入參) } } }; 說明:【實例化參數】可為空;【fnCont】為函數主體,函數名不可修改;當前一節【fnCont】等于上一節的【callback】即: A.callback() === B.fnCont() B.callback() === C.fnCont()鏈式調用回調函數都做了什么?
1、依照入參中的先后順序,動態組合了回調函數;
2、將當前的【callback】和下一個對象的【fnCont】進行映射綁定;使用過程應注意什么?
1、根據實際情況調整回調順序,或者增加方法;
2、每一節的callback即上下一節的fnCont;函數示例:
假設現在有3個需要同步執行的函數:FnA,FnB,FnC;
FnA的功能:將入參乘上10,然后傳給fnB,同時規定fnB的倒計時時間;
FnB的功能:進入倒計時,倒計時結束后,將入參乘上5,然后傳給fnC;
FnC的功能:將參數打印出來;// FnA的功能:將入參乘上10,然后執行FnB,同時設置fnB的倒計時時間(10s)... function FnA(arg,callback){ this.fnCont = function(){ var num = arg * 10 ; if(typeof callback == "function"){ callback(num,10); // 等價于【FnB】的fuCont } } } // FnB的功能:倒計時結束后,將入參乘上5,然后執行FnC ... function FnB(arg,callback){ this.fnCont = function(tArg,cDown){ var num = tArg * 5; var countDown = cDown; var tTout = setInterval(function(){ console.log("from FnB:進入倒計時 -> " + --countDown + "s"); if(countDown <= 0){ console.log("from FnB:倒計數結束"); countDown = -1; clearTimeout(tTout); if(typeof callback == "function"){ console.log("from FnB:執行回調函數"); callback(num);// 等價于【FnC】的fuCont } } },1000); } }; // 將參數打印出來 ... function FnC(arg,callback){ this.fnCont = function(tArg,awr){ console.log("from FnC:入參的值是" + tArg); if(typeof callback == "function"){ callback(); } } }; // 組合鏈式關系 ... chainedFn([ {"fnName":FnA,"fnArg":2}, //規定初始值 {"fnName":FnB},//倒計時結束后,進行一些操作 {"fnName":FnC},//展示處理結果 ]);執行結果:
from FnA:入參的值是 2 userCenter.js?v=undefined:63 from FnB:進入倒計時 -> 10s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 9s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 8s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 7s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 6s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 5s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 4s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 3s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 2s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 1s userCenter.js?v=undefined:65 from FnB:進入倒計時 -> 0s userCenter.js?v=undefined:67 from FnB:倒計數結束 userCenter.js?v=undefined:82 from FnC:入參的值是100
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/88571.html
摘要:回調函數,一般在同步情境下是最后執行的,而在異步情境下有可能不執行,因為事件沒有被觸發或者條件不滿足。同步方式請求異步同步請求當請求開始發送時,瀏覽器事件線程通知主線程,讓線程發送數據請求,主線程收到 一直以來都知道JavaScript是一門單線程語言,在筆試過程中不斷的遇到一些輸出結果的問題,考量的是對異步編程掌握情況。一般被問到異步的時候腦子里第一反應就是Ajax,setTimse...
摘要:函數會在之后的某個時刻觸發事件定時器。事件循環中的這樣一次遍歷被稱為一個。執行完畢并出棧。當定時器過期,宿主環境會把回調函數添加至事件循環隊列中,然后,在未來的某個取出并執行該事件。 原文請查閱這里,略有改動。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第四章。 現在,我們將會通過回顧單線程環境下編程的弊端及如何克服這些困難以創建令人驚嘆...
摘要:構造函數的實現我們在使用的時候其實是使用關鍵字創建了一個的實例,其實是一個類,即構造函數,下面來實現構造函數。 showImg(https://segmentfault.com/img/remote/1460000018998456); 閱讀原文 概述 Promise 是 js 異步編程的一種解決方案,避免了 回調地獄 給編程帶來的麻煩,在 ES6 中成為了標準,這篇文章重點不是敘...
摘要:引擎線程也稱為內核,負責處理腳本程序例如引擎引擎線程負責解析腳本,運行代碼。對象代表一個未完成但預計將來會完成的操作。注意一旦新建就會立即執行它屬于,無法取消。 寫在前面: 第一遍學Promise時, 只是大概過了一遍, 感覺學的不夠深入, 這一篇算是對之前的一個總結吧. Promise在ES6中也屬于一個較難理解的一部分; 所以在學習一個比較難理解的知識點時, 我們可以圍繞這個知識點...
閱讀 2757·2023-04-25 14:15
閱讀 2704·2021-11-04 16:11
閱讀 3395·2021-10-14 09:42
閱讀 442·2019-08-30 15:52
閱讀 2826·2019-08-30 14:03
閱讀 3546·2019-08-30 13:00
閱讀 2112·2019-08-26 11:40
閱讀 3308·2019-08-26 10:25