1. 程式人生 > >async 非同步流程控制

async 非同步流程控制

async是一個強大的非同步流程控制庫,其語義類似於js對陣列的操作。它提供了一系列非常強大而便捷的方法,有助於我們在javascript單執行緒模型背景下寫出優雅的邏輯控制程式碼。

牛刀小試

先從檔案操作開始初步瞭解async函式庫的作用:

  • 使用filter過濾出磁碟中存在的檔案
const fs = require('fs');  
const async = require('async');  

async.filter(['f1', 'f2', 'f3'], function(it, callback) {
    fs.access(it, function
(err) {
callback(null, !err); }); }, function(err, results) { console.log(results); });

假設當前目錄下存在以上三個檔案,那麼results輸出為:

['f1', 'f2', 'f3']
  • 使用map判斷檔案是否存在
async.map(['f1', 'f2', 'f3'], function(it, callback) {
  fs.exists(function(exists) {
      callback(null, exists);
  });
}, function
(err, results) {
console.log(results);//[true, true, true] });

以上兩個例子分別使用了accessexists判斷檔案是否存在,關於兩個API的詳細說明,請檢視nodejs官方文件

  • 常用的多工並行
function asyncTask(delay, arg) {
    return function(callback) {
        setTimeout(function() {
            console.log(arg + "done");
            callback(null
, arg); }, delay); }; } async.parallel([ asyncTask(10, "task1"), asyncTask(1, "task2"), asyncTask(100, "task3"), ], function(err, ret) { console.log(ret); });

asyncTask輸出的順序依次為:


[[email protected] async]$ node app.js
task2done
task1done
task3done
//ret
[ 'task1', 'task2', 'task3' ]

可見雖然任務是並行的,但是最終的結果依然按照任務陣列的順序排列。

  • 順序執行任務

function asyncTask(delay, arg) {
    return function(callback) {
        setTimeout(function() {
            console.log(arg + "done");
            callback(null, arg);
        }, delay);
    };
}

async.series([
    asyncTask(10, "task1"),
    asyncTask(1, "task2"),
    asyncTask(100, "task3"),
], function(err, ret) {
    console.log(ret);
});

輸出:

[[email protected] async]$ node app.js
task1done
task2done
task3done
[ 'task1', 'task2', 'task3' ]  

可以看到任務按照傳入的順序依次執行。

集合型別多工處理

  • each
    each函式依次遍歷陣列執行回撥函式:

function readFile(file, callback) {
    fs.readFile(file, function(err, ret) {
        console.log("readFile "+ file + " done");
        callback(err);
    });
}

async.each(['f1', 'f2', 'f3'], readFile, function(err) {
    console.log("all done");
});

需要注意的是,each不能保證迭代函式完成的順序,這取決於使用者的具體任務

  • forEachOf

each函式可以對陣列進行遍歷,如果想要遍歷的是一個物件,那麼需要用到forEachOf.

function readFile(file, k, callback) {
    fs.readFile(file, function(err, ret) {
        console.log("readFile "+ k + " " + file + " done");
        callback(err);
    });
}

async.forEachOf({k1: "f1", k2: "f2", k3: "f3"}, readFile, function(err) {
    console.log("all done");
});

迭代函式第一個引數是value,第二個引數是key.

  • 控制eachfoEachOf的順序
    eachSeriesforEachOf都是用來控制迭代函式的順序執行:

function readFile(file, k, callback) {
    fs.readFile(file, function(err, ret) {
        console.log("readFile "+ k + " " + file + " done");
        callback(err);
    });
}

async.forEachOfSeries({k1: "f1", k2: "f2", k3: "f3"}, readFile, function(err) {
    console.log("all done");
});

這樣程式的輸出始終是:

[[email protected] async]$ node app.js
readFile k1 f1 done  
readFile k2 f2 done
readFile k3 f3 done
all done
  • 使用apply包裝非同步任務

前面幾個非同步任務都需要人為的額外寫一個函式,如asyncTaskasync提供一個apply語法糖用於解決此類問題:


// 使用 apply

async.parallel([
    async.apply(fs.writeFile, 'testfile1', 'test1'),
    async.apply(fs.writeFile, 'testfile2', 'test2'),
]);


// 等同於

async.parallel([
    function(callback){
        fs.writeFile('testfile1', 'test1', callback);
    },
    function(callback){
        fs.writeFile('testfile2', 'test2', callback);
    }
]);
  • 使用Limit類函式控制併發數量

async為每個介面都提供了一個Limit引數,使用者限制併發數量,我們利用filterLimit做一個簡單的測試:


var count = 0;
async.filterLimit([1, 10, 28, 90, 10], 2, function(it, callback) {
    count++;
    console.log(it + "開始");
    console.log("併發數:", count);
    setTimeout(function() {
        count--;
        console.log(it + "結束");
        callback(null);
    }, it);
}, function(results) {
    console.log(results);
});

輸出:

[[email protected] async]$ node app.js 
1開始
併發數: 1
10開始
併發數: 2
1結束
28開始
併發數: 2
10結束
90開始
併發數: 2
28結束
10開始
併發數: 2
10結束
90結束
null

可以看到,最大併發數也就是2,雖然待執行任務大於2.

async幾乎提供了全類陣列操作型別的介面,例如:sortByreducesome等,這裡不再一一展開。

非同步控制函式

前面介紹了兩個非同步流程控制函式:seriesparallel。下面介紹其他幾個流程控制函式:

  • 使用whilst實現while操作

whilst用於實現,類似於while的效果,直到滿足條件,否則持續執行回撥函式。

var c = 0;

async.whilst(function() {
    console.log("judge");
    return c < 3;
}, function(callback) {
    c++;
    console.log("try " + c);
    setTimeout(function() {
        callback(null, c);
    }, 1000);
}, function(err, val) {
    console.log('err', err);
    console.log('value: ', val);
});

輸出:

[[email protected] async]$ node app.js 
judge
try 1
judge
try 2
judge
try 3
judge
err null
value:  3
  • 使用waterFall解決非同步任務依賴問題
async.waterfall([
    function(callback) {
        callback(null, 'one', 'two');
    },
    function(arg1, arg2, callback) {
      // arg1 now equals 'one' and arg2 now equals 'two'
        callback(null, 'three');
    },
    function(arg1, callback) {
        // arg1 now equals 'three'
        callback(null, 'done');
    }
], function (err, result) {
    // result now equals 'done'
});

相關推薦

async 非同步流程控制

async是一個強大的非同步流程控制庫,其語義類似於js對陣列的操作。它提供了一系列非常強大而便捷的方法,有助於我們在javascript單執行緒模型背景下寫出優雅的邏輯控制程式碼。 牛刀小試 先從檔案操作開始初步瞭解async函式庫的作用:

node.js對mongodb的連接&增刪改查(附async同步流程控制

color var literal int lba node () n! node.js 1.啟動mongodb數據庫 官網下載mongodb數據庫 在mongodb根目錄下創建文件夾:假設取名為test。 我們認為test就是mongodb新建的數據庫一枚。 創建批處理文

JavaScript非同步流程控制全攻略

一.js非同步流程的由來       眾所周知,Javascript語言的執行環境是單執行緒(single thread),作為瀏覽器指令碼語言,JavaScript的主要用途是與使用者互動,以及操作DOM。若以多執行緒的方式操作這些DOM,則可能出現操作

Nodejs:非同步流程控制(下)

//非同步操作,序列有關聯(瀑布流模式) //npm install async --save-dev var async = require('async'); function exec() { async.waterfall( [ fun

Nodejs:非同步流程控制(上)

function oneFun() { // setTimeout(function () { // console.log("a"); // }, 1000); i = 0; setInterval(function () {

node.js對mongodb的連線&增刪改查(附async同步流程控制

最近嘗試了node.js和mongodb的使用。下面來一波步驟。 1.啟動mongodb資料庫 官網下載mongodb資料庫 在mongodb根目錄下建立資料夾:假設取名為test。 我們認為test就是mongodb新建的資料庫一枚。 建立批處理

一道promise的小題目(Promise非同步流程控制

用Promise控制非同步流程,三個非同步任務,時間可能有先後,但是要按照想要的順序輸出。 我這裡用四種方法解決,其實也就是考察你對Promise的理解,基礎題了。 //實現mergePromise函式,把傳進去的陣列順序先後執行, //並且把返回的資料先後放到陣列data中 const timeout =

Node非同步爬蟲引出的非同步流程控制的一些問題

前記: 想寫一個電影天堂的爬蟲,因為node很長時間落下,就想用node去寫一下。結果遇到了一些列的問題,這些問題歸根到底就是非同步流程控制的問題,在以前就一直會接觸到很多回調地獄,Promise為什麼會出現諸如此類的話題,現在終於是深刻體會到了! 開始的程式碼是: const cheerio = requi

Node.js系列--非同步流程控制

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span><span style="font-

node js 非同步執行流程控制模組Async介紹

sync是一個流程控制工具包,提供了直接而強大的非同步功能。基於Javascript為Node.js設計,同時也可以直接在瀏覽器中使用。 Async提供了大約20個函式,包括常用的 map, reduce, filter, forEach 等,非同步流程控制模式包括,序列(series),並行(para

async異步流程控制

cno ace dea 方式 limit 中一 有關 參數 err http://cnodejs.org/topic/54acfbb5ce87bace2444cbfb 先安裝:G:\www\nodejs\one\models>npm install async --s

js非同步操作的流程控制——20181114

序列執行(程式碼可直接在console控制檯執行) var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function async(arg, callback) { console.log('引數為 ' + arg +' , 1秒後返回

現代JS中的流程控制:詳解Callbacks 、Promises 、Async/Await

JavaScript經常聲稱是_非同步_。那是什麼意思?它如何影響發展?近年來這種方法有何變化? 請思考以下程式碼: result1 = doSomething1(); result2 = doSomething2(result1); 大多數語言都處理每一行同步。第一行執行並返回結果。第二行在第一行完

node的async流程控制包parallel的實現

Async介紹 Async是一個流程控制工具包,提供了直接而強大的非同步功能。基於Javascript為Node.js設計,同時也可以直接在瀏覽器中使用。 Async提供了大約20個函式,包括常用的map, reduce, filter, forEach 等,非同步流程

JS的四種非同步方式:回撥/監聽/流程控制庫/promise

你可能知道,Javascript語言的執行環境是”單執行緒”(single thread)。 所謂”單執行緒”,就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行後面一個任務,以此類推。 這種模式的好處是實現起來比較簡單,執行環

Async詳解之一:流程控制

為了適應非同步程式設計,減少回撥的巢狀,我嘗試了很多庫。最終覺得還是async最靠譜。 Async的內容分為三部分: 流程控制:簡化十種常見流程的處理 集合處理:如何使用非同步操作處理集合中的資料 工具類:幾個常用的工具類 本文介紹其中最簡單最常用的流程控制部分。

C#基礎知識-流程控制的應用(四)

相關 ats 循環 nbsp 使用 logs 嘗試 exc 設置斷點 流程控制我們在編程中運用到的地方非常的多,在上篇中僅僅只是簡單的介紹每一種的使用,並沒有運用到實例中,很難去理解它真正的作用。下面我們將實際的運用流程控制的代碼寫一些實例相關的程序,加深對流程控制的理解,

js---11運算符,流程控制,真假

arr body color 空格 one round red 轉換 class <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="tex

JS3流程控制

代碼塊 語句 write 次循環 var break tex document if...else 比較簡單(與java中的流程控制一樣) 做判斷(if語句) if(條件){ 條件成立時執行代碼} 二選一 (if...else語句) if(條件){ 條件成立時執行的代碼}e

Shell腳本的基本流程控制

false 流程控制 ash lba -s print 所有 循環 數字 if else read -p ‘請輸入分數:‘ score if [ $score -lt 60 ]; then echo ‘60分以下‘ elif [ $score -lt 70 ]; th