成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

探索Javascript 異步編程

Salamander / 3393人閱讀

摘要:因?yàn)闉g覽器環(huán)境里是單線程的,所以異步編程在前端領(lǐng)域尤為重要。除此之外,它還有兩個(gè)特性,使它可以作為異步編程的完整解決方案函數(shù)體內(nèi)外的數(shù)據(jù)交換和錯(cuò)誤處理機(jī)制。

在我們?nèi)粘>幋a中,需要異步的場(chǎng)景很多,比如讀取文件內(nèi)容、獲取遠(yuǎn)程數(shù)據(jù)、發(fā)送數(shù)據(jù)到服務(wù)端等。因?yàn)闉g覽器環(huán)境里Javascript是單線程的,所以異步編程在前端領(lǐng)域尤為重要。

異步的概念

所謂異步,是指當(dāng)一個(gè)過(guò)程調(diào)用發(fā)出后,調(diào)用者不能立刻得到結(jié)果。實(shí)際處理這個(gè)調(diào)用的過(guò)程在完成后,通過(guò)狀態(tài)、通知或者回調(diào)來(lái)通知調(diào)用者。

比如我們寫(xiě)這篇文字時(shí)點(diǎn)擊發(fā)布按鈕,我們并不能馬上得到文章發(fā)布成功或者失敗。等待服務(wù)器處理,這段時(shí)間我們可以做其他的事情,當(dāng)服務(wù)器處理完成后,通知我們是否發(fā)布成功。

所謂同步,是指當(dāng)一個(gè)過(guò)程調(diào)用發(fā)出后,必須等待這個(gè)過(guò)程處理完成后,再處理其他事情。即堵塞執(zhí)行。

異步的方式

es6之前,我們實(shí)現(xiàn)異步有4種方法,回調(diào)、事件、發(fā)布訂閱和promise方式。

異步之回調(diào):
function dealTask(param, callback) {
    // Deal with some time consuming tasks.
    // ...
    Object.prototype.toString.call(callback) === "[object Function]" ? callback() : null; 
}
 
dealTask({ id: 1 }, function() {
    console.log("... I am in the callback...");
})

回調(diào)的方式來(lái)實(shí)現(xiàn)異步其實(shí)就是把需要在當(dāng)前任務(wù)完成后執(zhí)行的函數(shù)當(dāng)成參數(shù)傳入,完成任務(wù)后執(zhí)行即可。

異步之事件
function dealTask(param) {
    // Deal with some time consuming tasks.
    // ...
    events.trigger("dealTaskFinish")
}
events.on("dealTaskFinish", function() {
    console.log("...I am in the end...");
})

通過(guò)事件來(lái)實(shí)現(xiàn)回調(diào),好處是方便實(shí)用,跨模塊傳遞數(shù)據(jù)。壞處是,事件用的多了后業(yè)務(wù)邏輯混亂,不知道哪里注冊(cè)過(guò)哪里監(jiān)聽(tīng)過(guò)。

另外需要注意的是在web component場(chǎng)景下,mount后注冊(cè)過(guò)的事件需要在unmount釋放,不然會(huì)導(dǎo)致內(nèi)存泄露。

異步之發(fā)布訂閱

發(fā)布訂閱的簡(jiǎn)單例子是,一個(gè)開(kāi)關(guān),同時(shí)并聯(lián)幾個(gè)燈泡(在不同房間),觸發(fā)的時(shí)候,幾個(gè)燈泡都會(huì)得到指令,然后執(zhí)行發(fā)光的行為。

// 使用pubsubz實(shí)現(xiàn)
var testSubscriber = function(data ){
    console.log(data );
};
var testSubscription = pubsubz.subscribe( "example", testSubscriber );
pubsubz.publish( "example", "hello" );

訂閱發(fā)布與的性質(zhì)與"事件監(jiān)聽(tīng)"類(lèi)似,不同的是,我們可以通過(guò)查看"消息中心",了解存在多少信號(hào)、每個(gè)信號(hào)有多少訂閱者,從而監(jiān)控程序的運(yùn)行。

異步之Promise
function helloWorld (ready) {
    return new Promise(function (resolve, reject) {
        if (ready) {
            resolve("Hello World!")
        } else {
            reject("Good bye!")
        }
    })
}

helloWorld(true).then(function (message) {
    console.log(message)
}, function (error) {
    console.log(error)
})

Promises對(duì)象是CommonJS工作組提出的一種規(guī)范,是對(duì)異步編程的一種統(tǒng)一,其實(shí)也就是語(yǔ)法糖,可閱讀性變強(qiáng)了而已。

在ES6出來(lái)以后,我們的異步方式也發(fā)生了改變。

異步之Generator

Generator函數(shù)是協(xié)程在ES6的實(shí)現(xiàn),最大特點(diǎn)就是可以交出函數(shù)的執(zhí)行權(quán)(即暫停執(zhí)行)。

Generator函數(shù)可以暫停執(zhí)行和恢復(fù)執(zhí)行,這是它能封裝異步任務(wù)的根本原因。除此之外,它還有兩個(gè)特性,使它可以作為異步編程的完整解決方案:函數(shù)體內(nèi)外的數(shù)據(jù)交換和錯(cuò)誤處理機(jī)制。

function* Foo(x) {
  yield x + 1;

  var y = yield null;
  return x + y;
}

var foo = Foo(5);
foo.next();     // { value: 6, done: false }
foo.next();     // { value: null, done: false }
foo.next(8);    // { value: 13, done: true }

next方法返回值的value屬性,是Generator函數(shù)向外輸出數(shù)據(jù);next方法還可以接受參數(shù),這是向Generator函數(shù)體內(nèi)輸入數(shù)據(jù)。

yield命令用于將程序的執(zhí)行權(quán)移出Generator函數(shù),那么就需要一種方法,將執(zhí)行權(quán)再交還給Generator函數(shù)

上面的方式,是我們手動(dòng)調(diào)用Generator函數(shù)執(zhí)行,但是當(dāng)我們的需要執(zhí)行next方法很多時(shí),就需要Generator函數(shù)自動(dòng)執(zhí)行了。

Generator函數(shù)自動(dòng)執(zhí)行的意思是,通過(guò)一定的方法來(lái)自動(dòng)執(zhí)行next方法,比如:

function autoRunGen(gen){
  var g = gen();

  function next(data){
    var result = g.next(data);
    if (result.done) return result.value;
    result.value.then(function(data){
      next(data);
    });
  }
  next();
}

co模塊是TJ開(kāi)發(fā)的一個(gè)小工具,用于Generator函數(shù)的自動(dòng)執(zhí)行。他的主要思想和上面的代碼片段類(lèi)似。

使用co的前提條件是,Generator函數(shù)的yield命令后面,只能是Promise對(duì)象。

co(function *() {
    var data = yield $.get("/api/data");
    console.log(data);
    var user = yield $.get("/api/user");
    console.log(user);
    var products = yield $.get("/api/products");
    console.log(products);
});

co模塊使得我們可以像寫(xiě)同步代碼一樣,寫(xiě)異步代碼。

異步之a(chǎn)sync/await

async函數(shù)僅僅是Generator函數(shù)的語(yǔ)法糖。

var fs = require("fs");

var readFile = function (fileName) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fileName, function(error, data) {
      if (error) reject(error);
      resolve(data);
    });
  });
};

var gen = function* (){
  var f1 = yield readFile("/etc/a.js");
  var f2 = yield readFile("/etc/b.js");
  console.log(f1.toString());
  console.log(f2.toString());
};

使用async/await方式:

var asyncReadFile = async function (){
  var f1 = await readFile("/etc/a.js");
  var f2 = await readFile("/etc/b.js");
  console.log(f1.toString());
  console.log(f2.toString());
};

async函數(shù)就是將Generator函數(shù)的星號(hào)(*)替換成async,將yield替換成await,僅此而已。

不同的是,Generator執(zhí)行需要手動(dòng)執(zhí)行,而async函數(shù)可以自動(dòng)執(zhí)行,像寫(xiě)同步一樣寫(xiě)異步。Generator返回Iterator對(duì)象,async函數(shù)返回Promise對(duì)象。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90894.html

相關(guān)文章

  • JavaScript模塊化編程探索

    摘要:模塊化編程,已經(jīng)成為一個(gè)迫切的需求。隨著網(wǎng)站功能逐漸豐富,網(wǎng)頁(yè)中的也變得越來(lái)越復(fù)雜和臃腫,原有通過(guò)標(biāo)簽來(lái)導(dǎo)入一個(gè)個(gè)的文件這種方式已經(jīng)不能滿(mǎn)足現(xiàn)在互聯(lián)網(wǎng)開(kāi)發(fā)模式,我們需要團(tuán)隊(duì)協(xié)作模塊復(fù)用單元測(cè)試等等一系列復(fù)雜的需求。 隨著網(wǎng)站逐漸變成互聯(lián)網(wǎng)應(yīng)用程序,嵌入網(wǎng)頁(yè)的Javascript代碼越來(lái)越龐大,越來(lái)越復(fù)雜。網(wǎng)頁(yè)越來(lái)越像桌面程序,需要一個(gè)團(tuán)隊(duì)分工協(xié)作、進(jìn)度管理、單元測(cè)試等等......開(kāi)發(fā)...

    jayzou 評(píng)論0 收藏0
  • 翻譯連載 | 第 10 章:異步的函數(shù)式(上)-《JavaScript輕量級(jí)函數(shù)式編程》 |《你不知

    摘要:這就是積極的函數(shù)式編程。上一章翻譯連載第章遞歸下輕量級(jí)函數(shù)式編程你不知道的姊妹篇原創(chuàng)新書(shū)移動(dòng)前端高效開(kāi)發(fā)實(shí)戰(zhàn)已在亞馬遜京東當(dāng)當(dāng)開(kāi)售。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個(gè)流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅(jiān)實(shí)的梁柱;分享,是 CSS 里最閃耀的一瞥;總...

    Lucky_Boy 評(píng)論0 收藏0
  • JavaScript是如何工作的:Web Workers的構(gòu)建塊+ 5個(gè)使用他們的場(chǎng)景

    摘要:最后,提供個(gè)正確使用的場(chǎng)景。異步編程的一個(gè)很好的用例就請(qǐng)求。這意味著異步函數(shù)只能解決一小部分語(yǔ)言單線程中的局限性問(wèn)題。中有類(lèi)似的集群子進(jìn)程概念,他們也是多線程但是和還是有區(qū)別??捎玫奶匦杂捎诘亩嗑€程特性,工作者只能訪問(wèn)特性的一個(gè)子集。 showImg(https://segmentfault.com/img/bVblS8J?w=400&h=298); 這是專(zhuān)門(mén)探索 JavaScript...

    ningwang 評(píng)論0 收藏0
  • Promise in ECMAScript | 前端技術(shù)探索

    摘要:而納入規(guī)范的也是建立在基礎(chǔ)上的。繼續(xù)閱讀的相關(guān)解釋語(yǔ)法其中函數(shù)擁有兩個(gè)參數(shù)和??梢钥吹剑谡Z(yǔ)法上看,還是有點(diǎn)像回調(diào)函數(shù)那種形式的,囧。完成操作已經(jīng)成功執(zhí)行完畢。消費(fèi),即對(duì)的所代表的值進(jìn)行一系列的處理。 文 | Leigh,UPYUN 已獲得授權(quán)原文鏈接:http://t.cn/R403hc4 在 JavaScript 這么多年發(fā)展中,尤其在前端領(lǐng)域框架層出不窮,解決方案也琳瑯滿(mǎn)目,Pr...

    SillyMonkey 評(píng)論0 收藏0
  • Build Your Own Promise

    摘要:意味著代指的操作由于某些原因失敗。第一步構(gòu)造函數(shù)有三種狀態(tài),。這個(gè)構(gòu)造函數(shù)我們可以先這樣寫(xiě)創(chuàng)建一個(gè)時(shí),首先進(jìn)行狀態(tài)初始化。所有的都是的,而并不是所有的對(duì)象都是。 一、JavaScript異步編程背景 ? 從去年ES2015發(fā)布至今,已經(jīng)過(guò)去了一年多,ES2015發(fā)布的新的語(yǔ)言特性中最為流行的也就莫過(guò)于Promise了,Promise使得如今JavaScript異步編程如此輕松愜意...

    susheng 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<