摘要:完成請(qǐng)問(wèn)應(yīng)該如何安排操作流程上面代碼采用個(gè)回調(diào)函數(shù)的嵌套,不僅寫起來(lái)麻煩,容易出錯(cuò),而且難以維護(hù)串行執(zhí)行我們可以編寫一個(gè)流程控制函數(shù),讓它來(lái)控制異步任務(wù),一個(gè)任務(wù)完成以后,再執(zhí)行另一個(gè)。
前言
回調(diào)地獄
Javascript 語(yǔ)言的執(zhí)行環(huán)境是“單線程”(single thread)。所謂“單線程”,就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面一個(gè)任務(wù)。
這種模式的好處是實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單,執(zhí)行環(huán)境相對(duì)單純;壞處是只要有一個(gè)任務(wù)耗時(shí)很長(zhǎng),后面的任務(wù)都必須排隊(duì)等著,會(huì)拖延整個(gè)程序的執(zhí)行。常見(jiàn)的瀏覽器無(wú)響應(yīng)(假死),往往就是因?yàn)槟骋欢?JavaScript 代碼長(zhǎng)時(shí)間運(yùn)行(比如死循環(huán)),導(dǎo)致整個(gè)頁(yè)面卡在這個(gè)地方,其他任務(wù)無(wú)法執(zhí)行。
為了解決這個(gè)問(wèn)題,Javascript 語(yǔ)言將任務(wù)的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。
回調(diào)函數(shù)假定有兩個(gè)函數(shù)f1和f2,后者必須等到前者執(zhí)行完成,才能執(zhí)行。這時(shí),可以考慮改寫f1,把f2寫成f1的回調(diào)函數(shù)。
function f1(callback) { callback(); }事件監(jiān)聽(tīng)
f1.on("done", f2); function f1(){ setTimeout(function () { // f1的任務(wù)代碼 f1.trigger("done"); }, 1000); }發(fā)布訂閱
jQuery.subscribe("done", f2); function f1(){ setTimeout(function () { // f1的任務(wù)代碼 jQuery.publish("done"); }, 1000); } jQuery.unsubscribe("done", f2);
這種方法的性質(zhì)與”事件監(jiān)聽(tīng)”類似,但是明顯優(yōu)于后者。因?yàn)槲覀兛梢酝ㄟ^(guò)查看”消息中心”,了解存在多少信號(hào)、每個(gè)信號(hào)有多少訂閱者,從而監(jiān)控程序的運(yùn)行。
js異步操作流程控制如果有多個(gè)異步操作,就存在一個(gè)流程控制的問(wèn)題:確定操作執(zhí)行的順序,以后如何保證遵守這種順序
function async(arg, callback) { console.log("參數(shù)為 " + arg +" , 1秒后返回結(jié)果"); setTimeout(function() { callback(arg * 2); }, 1000); }
上面代碼的async函數(shù)是一個(gè)異步任務(wù),非常耗時(shí),每次執(zhí)行需要1秒才能完成,然后再調(diào)用回調(diào)函數(shù)。
如果有6個(gè)這樣的異步任務(wù),需要全部完成后,才能執(zhí)行下一步的final函數(shù)。
function final(value) { console.log("完成: ", value); }
請(qǐng)問(wèn)應(yīng)該如何安排操作流程?
async(1, function(value){ async(value, function(value){ async(value, function(value){ async(value, function(value){ async(value, function(value){ async(value, final); }); }); }); }); });
上面代碼采用6個(gè)回調(diào)函數(shù)的嵌套,不僅寫起來(lái)麻煩,容易出錯(cuò),而且難以維護(hù)
串行執(zhí)行我們可以編寫一個(gè)流程控制函數(shù),讓它來(lái)控制異步任務(wù),一個(gè)任務(wù)完成以后,再執(zhí)行另一個(gè)。這就叫串行執(zhí)行。(任務(wù)隊(duì)列)
let taskQueen = [1, 2, 3, 4, 5, 6]; let result = []; function invoke(curTask) { if (curTask) { console.log("當(dāng)前正在執(zhí)行任務(wù)", curTask); result.push(curTask + "完成"); } else { console.log("當(dāng)前任務(wù)全部完成"); } } invoke(taskQueen.shift());
var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function series(item) { if(item) { async( item, function(result) { results.push(result); return series(items.shift()); }); } else { return final(results); } } series(items.shift());并行
var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; items.forEach(function(item) { async(item, function(result){ results.push(result); if(results.length == items.length) { final(results); } }) });
上面代碼中,forEach方法會(huì)同時(shí)發(fā)起6個(gè)異步任務(wù),等到它們?nèi)客瓿梢院螅艜?huì)執(zhí)行final函數(shù)。
并行執(zhí)行的好處是效率較高,比起串行執(zhí)行一次只能執(zhí)行一個(gè)任務(wù),較為節(jié)約時(shí)間。但是問(wèn)題在于如果并行的任務(wù)較多,很容易耗盡系統(tǒng)資源,拖慢運(yùn)行速度。因此有了第三種流程控制方式
function launcher() { while(running < limit && items.length > 0) { var item = items.shift(); async(item, function(result) { results.push(result); running--; if(items.length > 0) { launcher(); } else if(running == 0) { final(results); } }); running++; } } launcher();promise
Promise 對(duì)象用于一個(gè)異步操作的最終完成(或失敗)及其結(jié)果值的表示。(簡(jiǎn)單點(diǎn)說(shuō)就是處理異步請(qǐng)求。我們經(jīng)常會(huì)做些承諾,如果我贏了你就嫁給我,如果輸了我就嫁給你之類的諾言。這就是promise的中文含義:諾言,一個(gè)成功,一個(gè)失敗。) -MDN
new Promise( /* executor */ function(resolve, reject) {...} );
一個(gè) Promise有以下幾種狀態(tài):
pending: 初始狀態(tài),不是成功或失敗狀態(tài)。
fulfilled: 意味著操作成功完成。
rejected: 意味著操作失敗。
then()var promise = new Promise(function(resolve, reject){ resolve("傳遞給then的值"); }); promise.then(function (value) { console.log(value); }, function (error) { console.error(error); });catch()
捕獲promise 運(yùn)行的各種錯(cuò)誤 promise.then(undefined, onRejected)
的語(yǔ)法糖
var promise = new Promise(function(resolve, reject){ resolve("傳遞給then的值"); }); promise.then(function (value) { console.log(value); }).catch(function (error) { console.error(error); });Promise.resolve && Promise.reject Promise.all
生成并返回一個(gè)新的promise對(duì)象。
參數(shù)傳遞promise數(shù)組中所有的promise對(duì)象都變?yōu)閞esolve的時(shí)候,該方法才會(huì)返回, 新創(chuàng)建的promise則會(huì)使用這些promise的值。
如果參數(shù)中的任何一個(gè)promise為reject的話,則整個(gè)Promise.all調(diào)用會(huì)立即終止,并返回一個(gè)reject的新的promise對(duì)象。
由于參數(shù)數(shù)組中的每個(gè)元素都是由 Promise.resolve 包裝(wrap)的,所以Paomise.all可以處理不同類型的promose對(duì)象。
var p1 = Promise.resolve(1), p2 = Promise.resolve(2), p3 = Promise.resolve(3); Promise.all([p1, p2, p3]).then(function (results) { console.log(results); // [1, 2, 3] });Promise.race
var p1 = Promise.resolve(1), p2 = Promise.resolve(2), p3 = Promise.resolve(3); Promise.race([p1, p2, p3]).then(function (value) { console.log(value); // 1 });
生成并返回一個(gè)新的promise對(duì)象。
參數(shù) promise 數(shù)組中的任何一個(gè)promise對(duì)象如果變?yōu)閞esolve或者reject的話, 該函數(shù)就會(huì)返回,并使用這個(gè)promise對(duì)象的值進(jìn)行resolve或者reject。
參考JavaScript Promise迷你書(中文版)
promise阮一峰(http://javascript.ruanyifeng....
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/89043.html
摘要:需求背景系統(tǒng)有數(shù)據(jù)識(shí)別數(shù)據(jù)脫敏邏輯,支持可配置規(guī)則,自定義等,需要進(jìn)行異構(gòu)數(shù)據(jù)同步,大數(shù)據(jù)量??捎眯苑治隹捎眯员砀穹治鰣?chǎng)景影響降級(jí)原因某臺(tái)數(shù)據(jù)同步下線無(wú)影響數(shù)據(jù)同步無(wú)狀態(tài),調(diào)度平臺(tái)重連其他的數(shù)據(jù)同步服務(wù)。 需求背景 系統(tǒng)有數(shù)據(jù)識(shí)別、數(shù)據(jù)脫敏邏輯,支持可配置規(guī)則,自定義等,需要進(jìn)行異構(gòu)數(shù)據(jù)同步,大數(shù)據(jù)量?,F(xiàn)在針對(duì)以下幾個(gè)需求進(jìn)行講解 1、支持冗余設(shè)計(jì)2、支持任務(wù)自動(dòng)分發(fā),支持自動(dòng)負(fù)載均衡...
摘要:第篇簡(jiǎn)單異構(gòu)系統(tǒng)之微服務(wù)一大致介紹因?yàn)樵诤竺嬉眉僧悩?gòu)系統(tǒng),所以才有了本章節(jié)的微服務(wù)本章節(jié)使用了最簡(jiǎn)單的請(qǐng)求截取的方式,截取不同的后綴做不同的響應(yīng)處理,簡(jiǎn)直二實(shí)現(xiàn)步驟添加服務(wù)端文件引入模塊創(chuàng)建獲得請(qǐng)求的路徑訪問(wèn),將會(huì)返回歡迎 SpringCloud(第 026 篇)簡(jiǎn)單異構(gòu)系統(tǒng)之 nodejs 微服務(wù) - 一、大致介紹 1、因?yàn)樵诤竺嬉?SpringCloud 集成異構(gòu)系統(tǒng),所...
摘要:只要指定過(guò)這些事件的回調(diào)函數(shù),這些事件發(fā)生時(shí)就會(huì)進(jìn)入任務(wù)隊(duì)列,等待主線程讀取。異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)主線程開(kāi)始執(zhí)行異步任務(wù),就是執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。 javascript語(yǔ)言是一門單線程的語(yǔ)言,不像java語(yǔ)言,類繼承Thread再來(lái)個(gè)thread.start就可以開(kāi)辟一個(gè)線程。所以,javascript就像一條流水線,僅僅是一條流水線而已,要么加工,要么包裝,不能同時(shí)進(jìn)行多個(gè)任...
摘要:這兩個(gè)操作符都是編譯器默認(rèn)引入了類,最后都調(diào)用方法返回對(duì)象,臨時(shí)對(duì)象被回收,因此效率極為低下 Java String類筆記 聲明 文章均為本人技術(shù)筆記,轉(zhuǎn)載請(qǐng)注明出處https://segmentfault.com/u/yzwall String的不可變性 String的不可變性 // String declaration public final class String ...
摘要:出場(chǎng)人物老張,水壺兩把普通水壺,簡(jiǎn)稱水壺會(huì)響的水壺,簡(jiǎn)稱響水壺。同步非阻塞老張還是覺(jué)得自己有點(diǎn)傻,于是變高端了,買了把會(huì)響笛的那種水壺。所謂阻塞非阻塞,僅僅對(duì)于老張而言。 1、例子 老張愛(ài)喝茶,廢話不說(shuō),煮開(kāi)水。出場(chǎng)人物:老張,水壺兩把(普通 水壺,簡(jiǎn)稱水壺;會(huì)響的水壺,簡(jiǎn)稱響水壺)。 1 老張把水壺放到火上,立等水開(kāi)。(同步阻塞) 老張覺(jué)得自己有點(diǎn)傻 2 老張把...
閱讀 4063·2021-11-16 11:44
閱讀 5320·2021-10-09 09:54
閱讀 2073·2019-08-30 15:44
閱讀 1750·2019-08-29 17:22
閱讀 2825·2019-08-29 14:11
閱讀 3452·2019-08-26 13:25
閱讀 2383·2019-08-26 11:55
閱讀 1677·2019-08-26 10:37