国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

基于Javascript 的異步編程分析

2015-07-13 12:25陳浩
電腦知識(shí)與技術(shù) 2015年13期

陳浩

摘要:異步編程帶來(lái)的問(wèn)題在客戶端Javascript中并不明顯,但隨著服務(wù)器端Javascript越來(lái)越廣的被使用,大量的異步IO操作使得該問(wèn)題變得明顯。許多不同的方法都可以解決這個(gè)問(wèn)題,本文針對(duì)此問(wèn)題討論了一些方法。

關(guān)鍵詞:異步編程;Javascript;異步IO

中圖分類(lèi)號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2015)13-0080-02

Abstract: Asynchronous programming problems caused by the client Javascript is not obvious, but with the server-side Javascript is used more widely, a large number of asynchronous IO operation so that the problem becomes apparent. Many different methods can solve this problem, this paper discusses some of the ways this problem.

Key words: Asynchronous Programming; Javascript; Asynchronous IO

1 JavaScript 異步編程簡(jiǎn)述

異步指的是函數(shù)的調(diào)用并不直接返回執(zhí)行的結(jié)果,而往往是通過(guò)回調(diào)函數(shù)異步的執(zhí)行?;卣{(diào)函數(shù),其實(shí)就是調(diào)用用戶提供的函數(shù),該函數(shù)往往是以參數(shù)的形式提供的?;卣{(diào)函數(shù)并不一定是異步執(zhí)行的。

varfn = function(callback) {

// do something here

callback.apply(this, para);

};

varmycallback = function(parameter) {

// do someting in customer callback

};

// call the fn with callback as parameter

fn(mycallback);

上述的例子中,回調(diào)函數(shù)是被同步執(zhí)行的。大部分語(yǔ)言都支持回調(diào),C++可用通過(guò)函數(shù)指針或者回調(diào)對(duì)象,Java一般也是使用回調(diào)對(duì)象。

在Javascript中有很多通過(guò)回調(diào)函數(shù)來(lái)執(zhí)行的異步調(diào)用,例如setTimeout()或者setInterval()

setTimeout(function(){

console.log("this will be exectued after 1 second!");

},1000);

上例中,setTimeout直接返回,匿名函數(shù)會(huì)在1000毫秒后異步觸發(fā)并執(zhí)行,完成打印控制臺(tái)的操作。也就是說(shuō)在異步操作的情境下,函數(shù)直接返回,把控制權(quán)交給回調(diào)函數(shù),回調(diào)函數(shù)會(huì)在以后的某一個(gè)時(shí)間片被調(diào)度執(zhí)行。之所以要實(shí)現(xiàn)異步,則需要熟悉Javascript的線程模型。

2 Javascript線程模型和事件驅(qū)動(dòng)

Javascript是單線程的,為了能實(shí)現(xiàn)異步執(zhí)行,就需要明白Javascript在瀏覽器中的事件驅(qū)動(dòng)(event driven)機(jī)制。事件驅(qū)動(dòng)一般通過(guò)事件循環(huán)(event loop)和事件隊(duì)列(event queue)來(lái)實(shí)現(xiàn)的。假定瀏覽器中有一個(gè)專(zhuān)門(mén)用于事件調(diào)度的實(shí)例,該實(shí)例可以是一個(gè)線程,我們可以稱(chēng)之為事件分發(fā)線程event dispatch thread,該實(shí)例的工作就是一個(gè)不結(jié)束的循環(huán),從事件隊(duì)列中取出事件,處理所有很事件關(guān)聯(lián)的回調(diào)函數(shù)(event handler)。注意回調(diào)函數(shù)是在Javascript的主線程中運(yùn)行的,而非事件分發(fā)線程中,以保證事件處理不會(huì)發(fā)生阻塞。

通過(guò)事件驅(qū)動(dòng)機(jī)制,可以想象Javascript的編程模型就是響應(yīng)一系列的事件,執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù)。很多UI框架都采用這樣的模型。異步的主要目的是處理非阻塞,在和HTML交互的過(guò)程中,會(huì)需要一些IO操作,如果這些操作是同步的,就會(huì)阻塞其它操作,用戶的體驗(yàn)就是頁(yè)面失去了響應(yīng)。

由此可見(jiàn)Javascript通過(guò)事件驅(qū)動(dòng)機(jī)制,在單線程模型下,以異步回調(diào)函數(shù)的形式來(lái)實(shí)現(xiàn)非阻塞的IO操作。

3 Javascript異步編程的缺陷

Javascript的單線程模型有很多好處,但同時(shí)也帶來(lái)了很多問(wèn)題。

3.1 代碼可讀性

如果某個(gè)操作需要經(jīng)過(guò)多個(gè)非阻塞的IO操作,每一個(gè)結(jié)果都是通過(guò)回調(diào)如下所示:

operation1(function(err, result) {

operation2(function(err, result) {

operation3(function(err, result) {

operation4(function(err, result) {

operation5(function(err, result) {

// do something useful

})

})

})

})

})

意大利面條式的代碼很難維護(hù)。這樣的情況更多的會(huì)發(fā)生在server side的情況下。

3.2 流程控制

異步帶來(lái)的另一個(gè)問(wèn)題是流程控制,例如要訪問(wèn)三個(gè)網(wǎng)站的內(nèi)容,當(dāng)三個(gè)網(wǎng)站的內(nèi)容都得到后,合并處理,然后發(fā)給后臺(tái)。具體代碼如下:

varurls = ['url1','url2','url3'];

var result = [];

for (var i = 0, len = urls.length(); i

$.ajax({

url: urls[i],

context: document.body,

success: function(){

//do something on success

result.push("one of the request done successfully");

if (result.length === urls.length()) {

//do something when all the request is completed successfully

}

}});

}

通過(guò)檢查result的長(zhǎng)度的方式來(lái)決定是否所有的請(qǐng)求都處理完成,這種方式不可靠。

3.3 異常和錯(cuò)誤處理

在異步的方式下,異常處理分布在不同的回調(diào)函數(shù)中,無(wú)法在調(diào)用的時(shí)候通過(guò)try…catch的方式來(lái)處理異常, 所以很難做到有效清楚。

4 改進(jìn)式Javascript異步編程方案

為了解決Javascript異步編程帶來(lái)的問(wèn)題,提出了以下改進(jìn)式解決方案。

Promise對(duì)象曾經(jīng)以多種形式存在于很多語(yǔ)言中。Promise的核心是它的then方法,我們可以使用這個(gè)方法從異步操作中得到返回值,或者是異常。then有兩個(gè)可選參數(shù),分別處理成功和失敗的情景。

var promise = doSomethingAync()

promise.then(onFulfilled, onRejected)

異步調(diào)用doSomethingAync返回一個(gè)Promise對(duì)象promise,調(diào)用promise的then方法來(lái)處理成功和失敗。和以前的區(qū)別在于,首先異步操作有了返回值,雖然該值只是一個(gè)對(duì)未來(lái)的承諾;其次通過(guò)使用then,程序員可以有效的控制流程異常處理,決定如何使用這個(gè)來(lái)自未來(lái)的值。

Promise提供更便捷的流程控制,例如Promise.all()可以解決需要并發(fā)的執(zhí)行若干個(gè)異步操作,等所有操作完成后進(jìn)行處理。

var p1 = async1();

var p2 = async2();

var p3 = async3();

Promise.all([p1,p2,p3]).then(function(){

// do something when all three asychronized operation finished

});

對(duì)于異常處理,

doA()

.then(doB)

.then(null,function(error){

// error handling here

})

如果doA失敗,它的Promise會(huì)被拒絕,處理鏈上的下一個(gè)onRejected會(huì)被調(diào)用,在這個(gè)例子中就是匿名函數(shù)function(error){}。比起原始的回調(diào)方式,不需要在每一步都對(duì)異常進(jìn)行處理。

5 總結(jié)

隨著ES6的定義,Javascript的語(yǔ)法變得越來(lái)越豐富,更多的功能帶來(lái)了很多便利,原本簡(jiǎn)潔,單一目的的Javascript變得復(fù)雜,要承擔(dān)更多的任務(wù),本文討論了一些方法,具體需要根據(jù)情況選擇一個(gè)適合的方法。

參考文獻(xiàn):

[1] 李世勝.基于預(yù)測(cè)的JavaScript類(lèi)型系統(tǒng)研究[J].計(jì)算機(jī)研究與發(fā)展,2012(2).

[2] 楊俊.JavaScript面向?qū)ο缶幊烫轿鯷J].辦公自動(dòng)化,2010(8).

[3] 錢(qián)宇虹.如何用Java回調(diào)和線程實(shí)現(xiàn)異步調(diào)用[J].軟件工程師,2013(10).

[4] 吳通.基于動(dòng)態(tài)分析的JavaScript代碼推薦[J].計(jì)算機(jī)工程,2014(10).

新丰县| 安阳市| 喀喇沁旗| 宁化县| 体育| 吴忠市| 信阳市| 长宁区| 栾城县| 柘荣县| 黎平县| 伊川县| 马鞍山市| 浪卡子县| 屏南县| 确山县| 临沂市| 仁寿县| 鹤庆县| 百色市| 会宁县| 堆龙德庆县| 余江县| 睢宁县| 定州市| 鲁山县| 阿克陶县| 丘北县| 宜阳县| 科技| 阳山县| 乌鲁木齐县| 宜宾县| 林西县| 长葛市| 广宗县| 崇明县| 泰宁县| 平潭县| 兴隆县| 延安市|