• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      基于Javascript 的異步編程分析

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

      陳浩

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

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

      中圖分類號:TP311 文獻標識碼:A 文章編號: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 異步編程簡述

      異步指的是函數(shù)的調(diào)用并不直接返回執(zhí)行的結(jié)果,而往往是通過回調(diào)函數(shù)異步的執(zhí)行?;卣{(diào)函數(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í)行的。大部分語言都支持回調(diào),C++可用通過函數(shù)指針或者回調(diào)對象,Java一般也是使用回調(diào)對象。

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

      setTimeout(function(){

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

      },1000);

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

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

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

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

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

      3 Javascript異步編程的缺陷

      Javascript的單線程模型有很多好處,但同時也帶來了很多問題。

      3.1 代碼可讀性

      如果某個操作需要經(jīng)過多個非阻塞的IO操作,每一個結(jié)果都是通過回調(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

      })

      })

      })

      })

      })

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

      3.2 流程控制

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

      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

      }

      }});

      }

      通過檢查result的長度的方式來決定是否所有的請求都處理完成,這種方式不可靠。

      3.3 異常和錯誤處理

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

      4 改進式Javascript異步編程方案

      為了解決Javascript異步編程帶來的問題,提出了以下改進式解決方案。

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

      var promise = doSomethingAync()

      promise.then(onFulfilled, onRejected)

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

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

      var p1 = async1();

      var p2 = async2();

      var p3 = async3();

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

      // do something when all three asychronized operation finished

      });

      對于異常處理,

      doA()

      .then(doB)

      .then(null,function(error){

      // error handling here

      })

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

      5 總結(jié)

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

      參考文獻:

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

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

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

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

      浪卡子县| 辉南县| 株洲市| 舒城县| 峡江县| 于都县| 贵南县| 昭平县| 汤阴县| 措勤县| 德清县| 古浪县| 罗定市| 东宁县| 台北市| 青海省| 岫岩| 南川市| 商洛市| 静乐县| 抚松县| 子长县| 门源| 钦州市| 界首市| 齐河县| 广安市| 上高县| 柳河县| 峡江县| 绍兴市| 凤阳县| 临桂县| 二连浩特市| 汉沽区| 塘沽区| 玉溪市| 府谷县| 清水县| 临漳县| 高青县|