欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于javascript的異步編程實例詳解

 更新時間:2017年04月10日 09:01:25   作者:布瑞澤的童話  
這篇文章主要介紹了基于javascript的異步編程,結(jié)合實例形式分析了javascript異步編程的原理、實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下

本文實例講述了基于javascript的異步編程。分享給大家供大家參考,具體如下:

異步函數(shù)這個術(shù)語有點名不副實,調(diào)用一個函數(shù)后,程序只在該函數(shù)返回后才能繼續(xù)。JavaScript程序員如果稱一個函數(shù)為異步的,其意思就是這個函數(shù)會導(dǎo)致將來再運行另一個函數(shù),后者取自于事件隊列。如果后面這個函數(shù)是作為參數(shù)傳遞給前者的,則稱其為回調(diào)函數(shù)。

callback

回調(diào)函數(shù)是異步編程最基本的方式。

采用這種方式,我們把同步操作變成了異步操作,主函數(shù)不會堵塞程序運行,相當于先執(zhí)行程序的主要邏輯,將耗時的操作推遲執(zhí)行。

回調(diào)函數(shù)的優(yōu)點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護。

我們定義一個delay函數(shù),它是異步的,也就是說它會拖延指定函數(shù)的執(zhí)行,從而使現(xiàn)在正在執(zhí)行的程序繼續(xù)執(zhí)行。delay函數(shù)如下:

function delay(time, callback) {
 setTimeout(function () {
 callback("Slept for "+time);
 }, time);
}

那么如果我要delay兩次呢?

delay(1000, function(msg) {
 console.log(msg);
 delay(1200, function (msg) {
 console.log(msg);
 }
})
//...waits 1000ms
// > "Slept for 1000"
//...waits another 1200ms
// > "Slept for 1200"

只有這樣我們才能夠確保兩個delay一個接一個的執(zhí)行。如果層次多了呢?就會形成回調(diào)地獄。當異步任務(wù)很多時,維護大量的callback將是一場災(zāi)難。

Promise

Promise是一個被納入ES6中的規(guī)范,各大框架也早已實現(xiàn)相關(guān)方法。

Promise可以理解為一個承諾,如果A調(diào)用B,B返回一個承諾給A,然后A就可以在寫計劃的時候這么寫,當B返回結(jié)果的時候,A就執(zhí)行方案1,如果B沒有返回A要的結(jié)果,A就執(zhí)行方案2。這樣一來,所有的潛在風(fēng)險就都在A的可控范圍之內(nèi)了。

我們看看ES6中promise的用法示例:

'use strict';
var promiseCount = 0; 
function testPromise() {
 var thisPromiseCount = ++promiseCount;
 var log = document.getElementById('log');
 log.insertAdjacentHTML('beforeend', thisPromiseCount +') Started (<small>Sync code started</small>)<br/>');
 // 我們創(chuàng)建一個新的Promise,期望3秒后得到結(jié)果
 var p1 = new Promise(
 //當Promise解決或拒絕時該函數(shù)被調(diào)用
 function(resolve, reject) {
  log.insertAdjacentHTML('beforeend', thisPromiseCount +') Promise started (<small>Async code started</small>)<br/>');
  // 創(chuàng)建異步操作
  window.setTimeout(
  function() {
   // 滿足Promise
   resolve(thisPromiseCount);
  }, Math.random() * 2000 + 1000);
  });
  // 當Promise被滿足時執(zhí)行
  p1.then(
  // 輸出信息和值
  function(val) {
   log.insertAdjacentHTML('beforeend', val +') Promise fulfilled (<small>Async code terminated</small>)<br/>');
  })
  .catch(
  // 當Promise被拒絕時執(zhí)行
   function(reason) {
   console.log('Handle rejected promise ('+reason+') here.');
   });
  log.insertAdjacentHTML('beforeend', thisPromiseCount +') Promise made (<small>Sync code terminated</small>)<br/>');
}

快速連續(xù)執(zhí)行函數(shù),得到結(jié)果:

說明1,2異步操作后正常順序執(zhí)行完畢。更多Promise的詳細用法請參考:MDN

很多框架也提供了Promise相關(guān)方法,這里我們以jQuery為例。

$("button").bind( "click", function() {
 $("p").append( "Started...");
 $("div").each(function( i ) {
 $( this ).fadeIn().fadeOut( 1000 * (i+1) );
 });
 $( "div" ).promise().done(function() {
 $( "p" ).append( " Finished! " );
 });
});

可以看到,當$("div")的所有任務(wù)執(zhí)行完畢后,就會調(diào)用最后的done操作。

Jquery中的Promise也可以代表多種結(jié)果,出現(xiàn)不同結(jié)果時會分別調(diào)用相應(yīng)的回調(diào)。我們以ajax調(diào)用為例。1.5之前版本中,代碼必須寫成這樣:

$.get('/getdata',{
 success:onSuccess,
 failure:onFailure,
 always:onAlways
});

而1.5+版本引入了Promise對象后??梢詫懗扇缦滦问剑?/p>

var promise = $.get('/getdata');
promise.done(onSuccess);
promise.fail(onFailure);
promise.always(onAlways);

那么這種變化有什么好處呢?為什么非要在觸發(fā)ajax調(diào)用之后再附加回調(diào)呢?如果ajax要實現(xiàn)很多效果,比如觸發(fā)動畫、插入html、鎖定輸入等,那么僅僅由負責(zé)發(fā)出請求那部分應(yīng)用代碼來處理所有這些效果,顯然很蠢。只傳遞Promise就顯得很優(yōu)雅。

更多詳細請參考:jquery

Promise雖然是很優(yōu)雅,但是也只是解決了回調(diào)地獄的問題,真正簡化javascript異步編程的還是Generator。

Generator

生成器是ES6中的語法。

何為生成器?讓我們先看看以下代碼:

function* quips(name) {
 yield "hello " + name + "!";
 yield "i hope you are enjoying the blog posts";
 if (name.startsWith("X")) {
 yield "it's cool how your name starts with X, " + name;
 }
 yield "see you later!";
}

你沒有看錯,這就是javascript代碼。是不是和你曾經(jīng)認識的javascript不太一樣。這個函數(shù)就叫做生成器函數(shù)。生成器函數(shù)看起來和普通的函數(shù)是不是有點相像呢?

它們的區(qū)別如下:

一般的函數(shù)以function開頭,而生成器函數(shù)以function* 開頭。

生成器函數(shù)中有一個特殊關(guān)鍵字就是yield,作用就是暫停函數(shù)。配合next方法來調(diào)用可以達到一步一步的執(zhí)行函數(shù)的目的。

我們看看next方法的使用:

> var iter = quips("jorendorff");
 [object Generator]
> iter.next()
 { value: "hello jorendorff!", done: false }
> iter.next()
 { value: "i hope you are enjoying the blog posts", done: false }
> iter.next()
 { value: "see you later!", done: false }
> iter.next()
 { value: undefined, done: true }

可以看到,每一次next方法后,生成器函數(shù)就執(zhí)行到下一個yield位置處。

下面我們講解如何通過生成器函數(shù)來取代回調(diào)函數(shù)。我們還是以一開始的多次延遲delay為例。

首先,我們需要定義一個生成器:

function* myDelayedMessages() {
 /* delay 1000 ms and print the result */
 /* delay 1200 ms and print the result */
}

然后我們需要設(shè)置delay時間來執(zhí)行指定操作,我們現(xiàn)在暫定為空函數(shù)。

function* myDelayedMessages() {
 console.log(delay(1000, function(){}));
 console.log(delay(1200, function(){}));
}

然后我們使用yield關(guān)鍵字:

function* myDelayedMessages() {
 console.log(yield delay(1000, function(){}));
 console.log(yield delay(1200, function(){}));
}

然后我們就需要指定一個函數(shù)run來調(diào)用生成器函數(shù)的next方法,并且將空函數(shù)改為參數(shù)resume:

function run(generatorFunction) {
 var generatorItr = generatorFunction(resume);
 function resume(callbackValue) {
 generatorItr.next(callbackValue);
 }
 generatorItr.next()
}

最后執(zhí)行代碼如下:

run(function* myDelayedMessages(resume) {
 console.log(yield delay(1000, resume));
 console.log(yield delay(1200, resume));
})
//...waits 1000ms
// > "Slept for 1000"
//...waits 1200ms
// > "Slept for 1200"

這樣就完美的避免了回調(diào)地獄噢!

更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript中json操作技巧總結(jié)》、《JavaScript切換特效與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》、《JavaScript動畫特效與技巧匯總》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運算用法總結(jié)

希望本文所述對大家JavaScript程序設(shè)計有所幫助。

相關(guān)文章

  • 基于javascript實現(xiàn)數(shù)字英文驗證碼

    基于javascript實現(xiàn)數(shù)字英文驗證碼

    這篇文章主要為大家詳細介紹了javascript實現(xiàn)數(shù)字英文驗證碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • JavaScript 不支持 indexof 該如何解決

    JavaScript 不支持 indexof 該如何解決

    indexOf() 方法可返回某個指定的字符串值在字符串中首次出現(xiàn)的位置。本文給大家介紹ie8 不支持 indexof 的解決方法
    2016-03-03
  • 發(fā)個自己寫的表格操作類(添加,刪除,排序,上移,下移)

    發(fā)個自己寫的表格操作類(添加,刪除,排序,上移,下移)

    發(fā)個自己寫的表格操作類(添加,刪除,排序,上移,下移)...
    2006-11-11
  • ES6知識點整理之模塊化的應(yīng)用詳解

    ES6知識點整理之模塊化的應(yīng)用詳解

    這篇文章主要介紹了ES6知識點整理之模塊化的應(yīng)用,結(jié)合實例形式分析了基于node.js環(huán)境下模擬ES6模塊化配置與使用相關(guān)操作技巧,需要的朋友可以參考下
    2019-04-04
  • 微信小程序自定義純凈模態(tài)框(彈出框)的實例代碼

    微信小程序自定義純凈模態(tài)框(彈出框)的實例代碼

    這篇文章主要介紹了微信小程序自定義純凈模態(tài)框(彈出框)的實例代碼,代碼簡答易懂,非常不錯,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Js判斷兩個數(shù)組是否相等的幾種常見場景

    Js判斷兩個數(shù)組是否相等的幾種常見場景

    無論是在開發(fā)中還是面試時,在js中判斷變量是否相等,都是一個比較常見的問題,這篇文章主要給大家介紹了關(guān)于Js判斷兩個數(shù)組是否相等的幾種常見場景,需要的朋友可以參考下
    2024-07-07
  • js鼠標及對象坐標控制屬性詳細解析

    js鼠標及對象坐標控制屬性詳細解析

    這篇文章主要是對js鼠標及對象坐標控制屬性進行了詳細的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • 詳解JavaScript數(shù)組的操作大全

    詳解JavaScript數(shù)組的操作大全

    這篇文章主要給大家介紹js數(shù)組的操作,數(shù)組的創(chuàng)建,數(shù)組元素的發(fā)那個吻,數(shù)組元素的添加,數(shù)組元素的刪除,數(shù)組的截取和合并,數(shù)組的拷貝,數(shù)組元素的排序,數(shù)組元素的字符串化等知識,對js數(shù)組的操作感興趣的朋友可以參考下本篇文章
    2015-10-10
  • 微信小程序動態(tài)顯示項目倒計時效果

    微信小程序動態(tài)顯示項目倒計時效果

    這篇文章主要為大家詳細介紹了微信小程序動態(tài)顯示項目倒計時,格式如4天7小時58分鐘39秒,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • javascript 同時在IE和FireFox獲取KeyCode的代碼

    javascript 同時在IE和FireFox獲取KeyCode的代碼

    以前一直在IE8中測試網(wǎng)站,后來寫的一部分含有Ajax的代碼出現(xiàn)了故障,不得已下載了Firefox以及它的插件Firebug,才發(fā)現(xiàn),F(xiàn)F不支持windows.event事件。于是換了一種思路。
    2010-02-02

最新評論