亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解js的異步編程技術(shù)的方法

 更新時(shí)間:2017年02月09日 08:12:19   作者:大菜鳥(niǎo)231  
本篇文章主要介紹了詳解js的異步編程技術(shù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

基于瀏覽器的事件輪詢機(jī)制(以及Node.js中的事件輪詢機(jī)制),JavaScript常常會(huì)運(yùn)行在異步環(huán)境中。由于JavaScript本身語(yǔ)言的特性(不需要程序員操控線程/進(jìn)程),在js中解決異步化編程的方法就顯得相當(dāng)重要??梢哉f(shuō)一個(gè)完整的項(xiàng)目中,js開(kāi)發(fā)人員是不可能不面對(duì)異步操作的。本文將詳細(xì)介紹幾種經(jīng)典JavaScript異步編程串行化方法,同時(shí)也將簡(jiǎn)單介紹一下ES6提供的Promise順序執(zhí)行方法。

一.回調(diào)函數(shù)

(1)經(jīng)典回調(diào)函數(shù)方式:嵌套內(nèi)聯(lián)函數(shù)

假設(shè)我們有一個(gè)ajax()方法,他接收一個(gè)url參數(shù),向該地址發(fā)起一個(gè)異步請(qǐng)求,在請(qǐng)求結(jié)束時(shí)執(zhí)行第二個(gè)參數(shù)—一個(gè)回調(diào)函數(shù):

ajax(url,function(result){
 console.log(result);
});

可以說(shuō)這種方式幾乎是每個(gè)前端開(kāi)發(fā)人員都用過(guò)的回調(diào)函數(shù)方式,有了這樣的回調(diào)機(jī)制,開(kāi)發(fā)人員就不用編寫(xiě)類(lèi)似下面這樣的代碼來(lái)推測(cè)服務(wù)器請(qǐng)求什么時(shí)候返回:

var result=ajax(url);
setTimeout(function(result){
 console.log(result);
},400);

大家應(yīng)該能明白我此處想表達(dá)的意思。我們?cè)O(shè)置了一個(gè)延遲400毫秒的定時(shí)器,來(lái)假設(shè)我們發(fā)出的ajax請(qǐng)求會(huì)在400毫秒之內(nèi)完成。否則,我們將會(huì)操作一個(gè)undefined的result。

但是有一個(gè)問(wèn)題隨著項(xiàng)目的擴(kuò)大漸漸浮現(xiàn)出來(lái):如果場(chǎng)景需要我們多層嵌套回調(diào)函數(shù),代碼將變得難以閱讀和維護(hù):

ajax(url0,function(result0){
 ajax(result0.url1,function(result1){
  ajax(result1.url2,function(result2){
   console.log(result2);
  });
 });
});

(2)調(diào)用外部函數(shù)

為了解決內(nèi)聯(lián)回調(diào)函數(shù)暴露出來(lái)的代碼混亂問(wèn)題,我們引入外部函數(shù)調(diào)用來(lái)解決類(lèi)似問(wèn)題:

function handle2(result){
 console.log(result);
}
function handle1(result){
 ajax(result.url,function(result){
  handle2(result);
 });
}
ajax(url,function(result){
 handle1(result);
});

通過(guò)這種拆分內(nèi)聯(lián)函數(shù),來(lái)調(diào)用外部函數(shù)的優(yōu)化方法,能極大的保持代碼的簡(jiǎn)潔性。

二.制定回調(diào)管理器

觀察流行的JavaScript流程控制工具,例如Nimble、Step、Seq,我們會(huì)學(xué)習(xí)到一種簡(jiǎn)潔的設(shè)計(jì)模式:通過(guò)回調(diào)管理器來(lái)控制異步JavaScript執(zhí)行流程,下面是一個(gè)典型的回調(diào)管理器的關(guān)鍵代碼示例:

var Flow={};
//設(shè)置next方法,在上一個(gè)方法完成時(shí)調(diào)用下一個(gè)方法
Flow.next=function(){
 if(this.stack[0]){
  //彈出方法棧中的第一個(gè)方法,并執(zhí)行他
  this.stack.shift()();
 }
};
//設(shè)置series方法,接收一個(gè)函數(shù)數(shù)組,并按序執(zhí)行
Flow.series=function(arr){
 this.stack=arr;
 this.next();
};

//通過(guò)Flow.series我們能夠控制傳入的函數(shù)的執(zhí)行順序
Flow.series([
  function(){
   //do something
   console.log(1);
   Flow.next();
  },
  function(next){
   //do something
   console.log(2);
   Flow.next();
  }
]);

我們初始化了一個(gè)Flow控制器,為他設(shè)計(jì)了series和next兩個(gè)函數(shù)屬性。在我們編寫(xiě)的業(yè)務(wù)方法內(nèi)部,在方法結(jié)尾處通過(guò)調(diào)用Flow.next()的方式來(lái)順序觸發(fā)下一個(gè)方法;通過(guò)執(zhí)行series方法來(lái)順序執(zhí)行異步函數(shù)。這種通過(guò)核心控制器來(lái)管理異步函數(shù)調(diào)用的方式簡(jiǎn)化了我們的編程過(guò)程,讓開(kāi)發(fā)人員能夠投入更多精力在業(yè)務(wù)邏輯上。

三.全局標(biāo)記控制

(1)簡(jiǎn)單計(jì)數(shù)器控制

也許上面介紹的異步方法仍然不能滿足實(shí)際開(kāi)發(fā)中的業(yè)務(wù)場(chǎng)景:假設(shè)我們有a(),b(),c()三個(gè)方法,a和b沒(méi)有依賴關(guān)系,可以異步進(jìn)行。但是c必須在a和b都完成之后才能觸發(fā)。為滿足這樣的邏輯實(shí)現(xiàn),我們加入一個(gè)全局計(jì)數(shù)器來(lái)控制代碼的執(zhí)行流程:

var flag=2;
var aValue,bValue;
function a(){
 aValue=1;
 flag--;
 c();
}
function b(){
 setTimeout(function(){
  bValue=2;
  flag--;
  c();
 },200);
}
function c(){
 if(flag==0){
  console.log("after a and b:"+(aValue+bValue));
 }
}
a();
b();

我們?cè)O(shè)置了一個(gè)全局變量flag來(lái)監(jiān)控方法a和方法b的完成情況。方法b通過(guò)設(shè)置一個(gè)200毫秒的定時(shí)器來(lái)模擬網(wǎng)絡(luò)環(huán)境,最終會(huì)在b方法執(zhí)行完成之后成功調(diào)用c方法。這樣我們就實(shí)現(xiàn)了對(duì)方法a(),b(),c()的依賴調(diào)用。

(2)面向數(shù)據(jù)的控制

當(dāng)上述方案在復(fù)雜場(chǎng)景下應(yīng)用時(shí),會(huì)出現(xiàn)如下問(wèn)題:產(chǎn)品經(jīng)過(guò)多個(gè)版本迭代,c方法依賴更多的方法,因此計(jì)數(shù)器flag需要不斷的變化;產(chǎn)品迭代過(guò)程中更換了開(kāi)發(fā)人員。當(dāng)出現(xiàn)上述兩種情況時(shí),代碼的邏輯將會(huì)變得混亂不堪,flag標(biāo)記符是否能保持簡(jiǎn)明正確很大程度上受到了產(chǎn)品迭代的影響。因此我們提出面向數(shù)據(jù)的優(yōu)化改進(jìn)。

在真實(shí)的開(kāi)發(fā)場(chǎng)景中,存在方法依賴的原因基本都是因?yàn)榇嬖跀?shù)據(jù)依賴,對(duì)于上面那個(gè)簡(jiǎn)單的示例:c方法依賴于a方法和b方法操作的結(jié)果,而不是依賴于flag是否為0。因此我們可以通過(guò)檢查依賴方法是否已經(jīng)完成了數(shù)據(jù)處理來(lái)代替檢查標(biāo)記符是否已經(jīng)被置為0,在這個(gè)例子中也就是在c方法中檢查aValue和bValue是否已經(jīng)完成了賦值:

function c(){
 if(aValue!==undefined && bValue!==undefined){
  console.log("after a and b:"+(aValue+bValue));
 }
}

針對(duì)更加通用的場(chǎng)景,我們將上述代碼修改為下:

var checkDependency={};
var aValue,bValue;
function a(){
 aValue=1;
 checkDependency.a=true;
 c();
}
function b(){
 setTimeout(function(){
  bValue=2;
  checkDependency.b=true;
  c();
 },200);
}
function c(){
 if(checkDependency.a && checkDependency.b){
  console.log("after a and b:"+(aValue+bValue));
 }
}
a();
b();

通過(guò)面向數(shù)據(jù)的檢查方式,未來(lái)擴(kuò)展時(shí),我們僅需要在新增的方法中增加對(duì)checkDependency對(duì)象的修改,并且在c方法中檢查相應(yīng)屬性的存在就能實(shí)現(xiàn)異步依賴方法的順序執(zhí)行。

四.ES6新增方法—Promise類(lèi)

為了解決JavaScript中異步方法的復(fù)雜性,官方引入了一種統(tǒng)一的控制方式:

var bool=false;
/*
 * 新建一個(gè)Promise實(shí)例,向構(gòu)造函數(shù)傳入一個(gè)異步執(zhí)行函數(shù)
 * 異步函數(shù)會(huì)接受兩個(gè)參數(shù),由Promise傳入,對(duì)應(yīng)then方法中傳入的方法
 */
var promise=new Promise(function(resolve,reject){
 setTimeout(function(){
  if(bool){
   //根據(jù)執(zhí)行情況相應(yīng)調(diào)用resolve和reject
   resolve(bool);
  }else{
   reject(bool);
  }
 },200);
});
//通過(guò)then向Promise實(shí)例傳入解決方法
promise.then(function resolve(result){
 console.log("success");
},function reject(result){
 console.log("failure");
});

上例代碼展示了一個(gè)基礎(chǔ)的Promise應(yīng)用,也許實(shí)際場(chǎng)景中更加多見(jiàn)的是下面這種鏈?zhǔn)秸{(diào)用:

new Promise(function(res,rej){
 if(/*異步調(diào)用成功*/){
  res(data);
 }else{
  rej(error);
 }
}).then(function resolve(result){
 console.log("success");
},function reject(result){
 console.log("failure");
});

如果對(duì)Promise感興趣的話,可以在網(wǎng)上尋找資料繼續(xù)深入學(xué)習(xí)!

關(guān)于Promise的兼容性,通常web前端JavaScript代碼中不會(huì)直接使用Promise(通過(guò)caniuse.com網(wǎng)站查詢發(fā)現(xiàn)Android4.4不支持Promise)。如果特別想使用的,往往會(huì)在項(xiàng)目中附帶一些補(bǔ)足兼容性的promise類(lèi)庫(kù);而后端Node.js可以放心使用Promise類(lèi)來(lái)管理異步邏輯。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • JavaScript學(xué)習(xí)筆記記錄我的旅程

    JavaScript學(xué)習(xí)筆記記錄我的旅程

    JavaScript和Java沒(méi)有直接的關(guān)系,唯一的關(guān)系就是JavaScript原名LiveScript,后來(lái)吸取了Java的一些特性,升級(jí)為JavaScript,JavaScript有時(shí)被簡(jiǎn)稱為JS
    2012-05-05
  • JavaScript基礎(chǔ)知識(shí)點(diǎn)歸納(推薦)

    JavaScript基礎(chǔ)知識(shí)點(diǎn)歸納(推薦)

    下面小編就為大家?guī)?lái)一篇JavaScript基礎(chǔ)知識(shí)點(diǎn)歸納(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • 在JavaScript中使用開(kāi)平方根的sqrt()方法

    在JavaScript中使用開(kāi)平方根的sqrt()方法

    這篇文章主要介紹了在JavaScript中使用開(kāi)平方根的sqrt()方法,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-06-06
  • JavaScript字符串對(duì)象substring方法入門(mén)實(shí)例(用于截取字符串)

    JavaScript字符串對(duì)象substring方法入門(mén)實(shí)例(用于截取字符串)

    這篇文章主要介紹了JavaScript字符串對(duì)象substring方法入門(mén)實(shí)例,substring方法通過(guò)指定開(kāi)始和結(jié)束位置來(lái)截取字符串,需要的朋友可以參考下
    2014-10-10
  • 深入解析JavaScript中的arguments對(duì)象

    深入解析JavaScript中的arguments對(duì)象

    arguments是JavaScript里的一個(gè)內(nèi)置對(duì)象,像數(shù)組結(jié)構(gòu)一樣存儲(chǔ)參數(shù)的傳遞,這里我們就來(lái)深入解析JavaScript中的arguments對(duì)象,需要的朋友可以參考下
    2016-06-06
  • RGB和YUV 多媒體編程基礎(chǔ)詳細(xì)介紹

    RGB和YUV 多媒體編程基礎(chǔ)詳細(xì)介紹

    這篇文章主要介紹了 RGB和YUV 多媒體編程基礎(chǔ)詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • php的文件上傳入門(mén)教程(實(shí)例講解)

    php的文件上傳入門(mén)教程(實(shí)例講解)

    文件作為一種特殊的表單數(shù)據(jù),通過(guò)http post請(qǐng)求方式提交至服務(wù)器的時(shí)候,php會(huì)生成一個(gè)$_FILES全局?jǐn)?shù)組,相關(guān)的文件信息會(huì)存放在這個(gè)全局?jǐn)?shù)組中。我將在這篇文章中通過(guò)一些示例代碼來(lái)闡述php下的文件上傳,并且深入看下關(guān)于文件上傳內(nèi)部的實(shí)現(xiàn)機(jī)制,最后簡(jiǎn)單說(shuō)下如何加強(qiáng)這方面的安全性!
    2014-04-04
  • JavaScript中數(shù)組繼承的簡(jiǎn)單示例

    JavaScript中數(shù)組繼承的簡(jiǎn)單示例

    這篇文章主要介紹了JavaScript中數(shù)組繼承的簡(jiǎn)單示例,數(shù)組繼承是JavaScript入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • 簡(jiǎn)單了解常用的JavaScript 庫(kù)

    簡(jiǎn)單了解常用的JavaScript 庫(kù)

    這篇文章主要介紹了JavaScript 庫(kù)的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下
    2020-07-07
  • javascript 數(shù)據(jù)類(lèi)型轉(zhuǎn)換(parseInt,parseFloat)

    javascript 數(shù)據(jù)類(lèi)型轉(zhuǎn)換(parseInt,parseFloat)

    Number、String函數(shù)是特殊的函數(shù),在JS引擎中,他會(huì)自動(dòng)判斷是作為構(gòu)造函數(shù)調(diào)用還是普通調(diào)用,所以既可以使用new關(guān)鍵字,也可以作為函數(shù)直接調(diào)用。
    2010-07-07

最新評(píng)論