1. Basic process

Serial process, parallel process, mixed execution series, waterfall; parallel, parallelLimit; auto;

1.1. Serial processes

1.1.1.series (Multiple functions executed sequentially without data exchange)

There are multiple asynchronous functions that need to be called one by one before the next can be executed. There is no exchange of data between functions, just the order of execution. Use series.

async.series([ function(callback) { // do some stuff ... callback(null, 'one');  }, function(callback) { // do some more stuff ... callback(null, 'two');  } ], // optional callback function(err, results) { // results is now equal to ['one', 'two'] });Copy the code

It is also important to note that multiple series calls are in no particular order, since series itself is also an asynchronous call.

1.1.2. waterfall (Multiple functions are executed sequentially, and the output of the former one is the input of the latter)

Similar to SeIRES, multiple functions are executed in sequence. The difference is that each function produces a value that is passed to the next function. If an error occurs, subsequent functions will not be executed. Error messages, along with results previously generated, will be passed to Waterfall’s eventual callback.

Note that this function does not support JSON-formatted Tasks.

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' });Copy the code

1.2. Parallel processes

1.2.1. Parallel (Multiple functions executed in parallel)

Execute multiple functions in parallel. Each function executes immediately, without waiting for other functions to execute first. The data in the array passed to the final callback is in the order declared in tasks, not the order in which the execution was completed.

If a function fails, the parallel final callback is immediately passed the value of err and the result of the already executed function. Values of other unfinished functions do not pass to the final data, but take up space.

Json tasks are also supported, and the result of the callback is also JSON.

Sample code:

async.parallel([ function(callback) { setTimeout(function() { callback(null, 'one'); }, 200);  }, function(callback) { setTimeout(function() { callback(null, 'two'); }, 100);  } ], // optional callback function(err, results) { // the results array will equal ['one','two'] even though // the second function had a shorter timeout. });Copy the code

Pass the tasks as JSON

async.parallel({
    one: function(callback) {
        setTimeout(function() {
            callback(null, 1);
        }, 200);
    },
    two: function(callback) {
        setTimeout(function() {
            callback(null, 2);
        }, 100);
    }
}, function(err, results) {
    // results is now equals to: {one: 1, two: 2}
});
Copy the code

1.2.2. ParallelLimit (Limit the maximum number of functions executed in parallel)

ParallelLimit differs from Parallel above in that it limits the maximum number of simultaneous executions

async.parallelLimit([(cb) => { setTimeout(() => { cb(null, 'one'); }, 1000);  }, (cb) => { setTimeout(() => { cb(null, 'two'); }, 2000); }], 1, (err, value) => { log(value); }); // It takes about 3sCopy the code

1.3. Mixed execution

1.3.1. Auto (Tasks, [callback])

Used to handle the execution of multiple dependent tasks. For example, some tasks are independent of each other and can be executed in parallel. But some tasks depend on other tasks and can’t be performed until those tasks are complete.

Such as asynchronously fetching two pieces of data and printing:

async.auto({
  getData: function (callback) {
    setTimeout(() => {
      log('data got')
      callback(null, 'data');
    }, 3000);
  },
  getAnotherData: function (callback) {
    setTimeout(() => {
      log('another data got')
      callback(null, 'another data');
    }, 1000);
  },
  printData: ['getData', 'getAnotherData', function (result, callback) {
    log(result);
  }]
});
// another data got
// data got
// { getAnotherData: 'another data', getData: 'data' }
Copy the code

1.3.2. AutoInject (Tasks, callbackopt) (similar to Auto but the callback function is passed as an argument to the next serial function)

Dependent tasks are specified as parameters to the function

It’s the syntactic sugar of the auto method

async.autoInject({
    getData: function (callback) {
        axios({ methods: 'get', url: 'http://baidu.com/' }).then(d => callback(null, d.status))
    },
    getAnotherData: function (callback) {
        axios({ methods: 'get', url: 'http://sogou.com/' }).then(d => callback(null, d.status))
    },
    writeFile: function (getData, getAnotherData, callback) {
        fs.writeFile('./d.json', JSON.stringify([getData, getAnotherData]), function (err) {
            if (err) { callback(err) } else { callback(null, 'finish') }
        })
    }
}, function (err, result) {
    if (err) { console.log(err) } else {
        console.log(result) // { getData: 200, getAnotherData: 200, writeFile: 'finish' }
    }
})
Copy the code

2. Cycle

2.1. Whilst (used for asynchronous invocation)

Equivalent to while, but the asynchronous call will complete before the next loop. Examples are as follows:

var count = 0; async.whilst( () => { return count < 5; }, // if the condition (callback) => {// if the condition (count++); setTimeout(() => { log(count) callback(null, count); }, 1000); }, (err, value) => {// Do not meet the condition to complete the loop log('result: '+ count); });Copy the code

2.2. DoWhilst (post-validated asynchronous while)

Execute the function first

count = 0;
async.doWhilst((callback) => { // 先执行函数
  count++;
  setTimeout(() => {
    log(count);
    callback(null, count);
  }, 1000);
}, () => { // 后验证条件
  return count < 5;
}, (err, value) => { // 主回调
  log('result: ' + count);
});
Copy the code

2.3. It is similar to while, but the judgment condition is opposite.

var count = 0; async.until( () => { return count >= 5; }, (callback) => { count++; setTimeout(() => { log(count) callback(null, count); }, 1000); }, (err, value) => { log('result: ' + count); });Copy the code

2.4. DoUntil (post-validate Until loop)

var count = 0; Async.dountil ((callback) => {// count++; setTimeout(() => { log(count) callback(null, count); }, 1000); }, () => { return count >= 5; }, / / validation (err, value) = > {log (' result: '+ count); });Copy the code

2.5. during (类似whilst,回调判断)

Similar to whilst, it tests the callback (ERR, true or false) of an asynchronous function to see if the callback’s second argument is true

count = 0
async.during(callback => {
    callback(null, count < 5)
}, callback => {
    count++
    console.log(count)
    setTimeout(callback, 1000);
}, err => {
    if (err) console.log(err)
    console.log('finish')
})
Copy the code

2.6. DoDuring (similar to doWhilst)

Count = 0 async.doDuring(function (callback) {count++; log(count); setTimeout(callback, 1000); }, function (callback) {return (null, count < 5); }, function (err) { // 5 seconds have passed log('finished'); });Copy the code

2.7. Retry (Repeat as often as possible to a successful position)

No more than a specified number of attempts can be made to get a successful response from a function before an error is returned. If the task succeeds, the callback passes the result of the successful task. If all attempts fail, the callback passes the error and result of the final attempt.

async.retry({times: 3, interval: 200}, apiMethod, function(err, result) { log(result); }); // Try three times, at intervals of 200, to print the resultCopy the code

2.8. retryable

The packaging task enables it to be retry

async.auto({
    dep1: async.retryable(3, getFromFlakyService),
    process: ["dep1", async.retryable(3, function (results, cb) {
        maybeProcessData(results.dep1, cb);
    })]
}, callback);
Copy the code

2.9. Times (repeated n times)

Called n times, the ordinal n can be passed into the function as an argument

async.times(5, (n, next) => {
    axios({ methods: 'get', url: 'http://sogou.com/' }).then(d => next(null, d.status)).catch(e => next(e))
}, (err, result) => {
    if (err) {
        console.log(err)
    } else {
        console.log(result) // [ 200, 200, 200, 200, 200 ]
    }
})
Copy the code

2.10. TimesLimit (similar to times, but limiting the maximum number of concurrent executions)

timesLimit(count, limit, iteratee, callback)
Copy the code

2.11. TimesSeries (only one can be executed in parallel)

The same as times but runs only a single async operation at a time.

timesSeries(n, iteratee, callback)
Copy the code

2.12.forever (will be allowed to always execute — call yourself unless an error is caught)

Remember to call next

async.forever((next) => { setTimeout(() => { axios({ methods: ‘get’, url: ‘http://www.baidu.com/’ }).then(d => console.log(d.status)).then(next) }, 1000) }, error => { if (error) { console.log(error) } })

3. Assemble the process

Async provides a number of functions for collections that simplify the steps we take when we operate on collections asynchronously

3.1. The elements in the each collection execute functions

Execute the same function on all elements in all sets, in parallel:

Note, that since this function applies iteratee to each item in parallel, there is no guarantee that the iteratee functions will complete in order. There is no guarantee of sequential completion

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; async.each(data, (item, callback) => { console.log('processing... ' + item); axios({ methods: 'get', url: item }).then(d => { console.log(d.data.length); callback(); }); }, (err) => { if (err) console.log(err); }); // processing... http://www.baidu.com // processing... http://www.sogou.com // processing... http://www.bing.com // 22430 // 111984 // 116593Copy the code

3.2. eachLimit

The same as each but runs a maximum of limit async operations at a time.

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; async.eachLimit(data, 2, (item, callback) => { console.log('processing... ' + item); axios({ methods: 'get', url: item }).then(d => { console.log(d.data.length); callback(); }); }, (err) => { if (err) console.log(err); }); // processing... http://www.baidu.com // processing... http://www.sogou.com // 22430 // processing... http://www.bing.com // 112087 // 116593Copy the code

3.3. eachOf/forEachOf

Like each, except that it passes the key (or index) as the second argument to the iteratee. The function is executed with three arguments: item, index, and callback

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; // async. ForEachOf (data, (item, index, callback) => {forEachOf(data, (item, index, callback); callback) => { console.log('processing... NO.' + index); axios({ methods: 'get', url: item }).then(d => { console.log(d.data.length); callback(); }); }, (err) => { if (err) console.log(err); }); // processing... NO.0 // processing... NO.1 // processing... NO.2 // 112477 // 22430 // 116593Copy the code

3.4. eachOfLimit/forEachOfLimit

The same as eachOf but runs a maximum of limit async operations at a time. Multiple limiting parameters, no more verbose

3.5. eachOfSeries/forEachOfSeries

The same as eachOf but runs only a single async operation at a time. That equals eachOfLimit of 1

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; async.eachOfSeries(data, (item, index, callback) => { console.log('processing... NO.' + index); axios({ methods: 'get', url: item }).then(d => { console.log(d.data.length); callback(); }); }, (err) => { if (err) console.log(err); }); // processing... NO.0 // 111979 // processing... NO.1 // 22430 // processing... NO.2 // 116593Copy the code

3.6. eachSeries/forEachSeries

EachLimit = 1

3.7. Map returns the set of results of the collection data execution function

There is no guarantee that the iteratee functions will complete in order

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; async.map(data, (item, callback) => { console.log('processing... NO.' + item); axios({ methods: 'get', url: item }).then(d => { callback(null, d.data.length); }); }, (err, value) => { if (err) console.log(err); console.log(value); }); // processing... NO.http://www.baidu.com // processing... NO.http://www.sogou.com // processing... NO.http://www.bing.com // [112677, 22430, 116593]Copy the code

3.8. mapLimit

Similar to MAP, there are more limiting parameters

3.9. mapSeries

Equivalent to mapLimit restriction 1

3.10. mapValues

For handling objects

A relative of map, designed for use with objects. For the case of traversing an object value

let obj = { site1: 'http://www.baidu.com', site2: 'http://www.sogou.com', site3: 'http://www.bing.com' }; async.mapValues(obj, (value, key, callback) => { console.log('processing... NO.' + key); axios({ methods: 'get', url: value }).then(d => { callback(null, d.data.length); }); }, (err, value) => { if (err) console.log(err); console.log(value); }); // processing... NO.site1 // processing... NO.site2 // processing... NO.site3 // { site1: 112122, site2: 22430, site3: 116593 }Copy the code

3.11. mapValuesLimit

Too many limiting parameters

3.12. mapValuesSeries

Equivalent to mapValuesLimit Limit 1

3.13. Filter Returns the original element that meets the criteria

The raw data that passed the test is returned, only filtered, without modifying the raw data

Returns a new array of all the values in coll which pass an async truth test. Filtering returns the verified result as true

This operation is performed in parallel, but the results array will be in the same order as the original. The final result will be in the same order as the original data

let data = [ 'http://www.baidu.com', 'http://www.sogou.com', 'http://www.bing.com', ]; async.filter(data, (item, callback) => { console.log('processing... NO.' + item); axios({ methods: 'get', url: item }).then(d => { let length = d.data.length; if (length > 100000) { callback(null, true); } else { callback(null, false); }}); }, (err, value) => { if (err) console.log(err); console.log(value); }); // processing... NO.http://www.baidu.com // processing... NO.http://www.sogou.com // processing... NO.http://www.bing.com // ['http://www.baidu.com', 'http://www.bing.com']Copy the code

3.14. filterLimit

.

3.15. filterSeries

.

Reject (as opposed to filter)

In contrast to filter, those that pass verification are eliminated

The opposite of filter. Removes values that pass an async truth test.

3.17. rejectLimit

.

3.18. rejectSeries

.

3.19. Detect the first to meet the condition

Returns the first value in coll that passes an async truth test. Gets the first data in the collection that satisfies the test

let data = [ 'http://www.sogou.com', 'http://www.baidu.com', 'http://www.bing.com', ]; async.detect(data, (item, callback) => { console.log('processing... NO.' + item); axios({ methods: 'get', url: item }).then(d => { let length = d.data.length; if (length > 100000) { callback(null, true); } else { callback(null, false); }}); }, (err, value) => { if (err) console.log(err); console.log(value); }); // processing... NO.http://www.sogou.com // processing... NO.http://www.baidu.com // processing... NO.http://www.bing.com // http://www.baidu.comCopy the code

3.20. detectLimit

.

3.21. detectSeries

.

3.22. Some /any has at least one eligible trigger main callback

If any iteratee call returns true, the main callback is immediately called. The main callback is triggered as soon as the data meets the criteria

let data = [ 'http://www.sogou.com', 'http://www.baidu.com', 'http://www.bing.com', ]; async.some(data, (item, callback) => { axios({ methods: 'get', url: item }).then(d => { let length = d.data.length; if (length > 100000) { callback(null, true); } else { callback(null, false); }}); }, (err, isSatisfied) => { if (err) console.log(err); console.log(isSatisfied); // true });Copy the code

3.23. someLimit/anyLimit

.

3.24. someSeries/anySeries

.

3.25. Return true for every/all

Returns true if every element in coll satisfies an async test. If any iteratee call returns false, the main callback is immediately called. Return true if all conditions are met

let data = [ 'http://www.sogou.com', 'http://www.baidu.com', 'http://www.bing.com', ]; async.every(data, (item, callback) => { axios({ methods: 'get', url: item }).then(d => { let length = d.data.length; if (length > 0) { callback(null, true); } else { callback(null, false); }}); }, (err, isSatisfied) => { if (err) console.log(err); console.log(isSatisfied); // true });Copy the code

3.26. everyLimit/allLimit

.

3.27. everySeries/allSeries

.

3.28. Concat merge results

Merging the results, again, does not guarantee that the results will be sorted in the original order

let data = [
  'http://www.sogou.com',
  'http://www.baidu.com',
  'http://www.bing.com',
];

async.concat(data, (item, callback) => {

  axios({
    methods: 'get',
    url: item
  }).then(d => {
    callback(null, { item: item, length: d.data.length });
  });

}, (err, value) => {
  if (err) console.log(err);
  console.log(value);
});
// [ { item: 'http://www.sogou.com', length: 22430 },
//   { item: 'http://www.baidu.com', length: 111979 },
//   { item: 'http://www.bing.com', length: 116550 } ]
Copy the code

3.29. concatLimit

.

3.30. concatSeries

.

3.31. GroupBy Results are grouped according to the key of the object

A series of objects are passed in and grouped according to the set key

let data = [{ year: 2001, url: 'http://www.baidu.com' }, { year: 2001, url: 'http://www.sogou.com' }, { year: 2017, url: 'http://www.bing.com' }] async.groupBy(data, (item, callback) => { axios({ methods: 'get', url: item.url }).then(d => { callback(null, item.year); // Group by year}); }, (err, value) => { if (err) console.log(err); console.log(value); }); // { // '2001': // [{ year: 2001, url: 'http://www.baidu.com' }, // { year: 2001, url: 'http://www.sogou.com' }], // '2017': [{ year: 2017, url: 'http://www.bing.com' }] // }Copy the code

3.32. groupByLimit

.

3.33. groupBySeries

.

3.34. Reduce Serial accumulation of set data

− − Reduces coll into a single value

This function only operates in series. Only series mode is supported. Parallelism is not supported

This function is for situations where each step in the reduction needs to be async; if you can get the data before reducing it, then it’s probably a good idea to do so. This scenario is suitable for asynchronous data acquisition in each Reduce step

Async. Reduce ([2, 3, 4], 1, (memo, item, callback) => {// 1 indicates memo setTimeout(() => {callback(null, memo + item); }, 100); }, (err, value) => { if (err) console.log(err); console.log(value); / / 10});Copy the code

3.35. reduceRight

Same as reduce, only operates on array in reverse order. Similar to reduce

.

3.36. SrotBy is arranged in order

Order (item/item * -1)

async.sortBy([13, 21, 321, 421, 3, 21, , , , 23121, 1], (item, callback) => { setTimeout(() => { callback(null, item * -1); // callback(null, item); }, 100); }, (err, value) => { if (err) console.log(err); console.log(value); }); // [23121, 421, 321, 21, 21, 13, undefined, undefined, undefined, 3, 1]Copy the code

3.37. Transform transforms a collection by some rule

Acc means accumulate and obj is object

async.transform([1, 2, 3], (acc, item, index, callback) => {

  setTimeout(() => {
    acc.push(index + ': ' + item);
    callback(null);
  }, 100);

}, (err, value) => {
  if (err) console.log(err);
  console.log(value);
});
// ['0: 1', '1: 2', '2: 3']
Copy the code

Examples of objects:

async.transform({ name: 'oli', age: 12 }, (obj, val, key, callback) => { setTimeout(() => { obj[key] = val + '... '; callback(null); }, 100); }, (err, value) => { if (err) console.log(err); console.log(value); }); // { name: 'oli... ', age: '12... '}Copy the code

4. Other

4.1. tryEach ()

If one of the tasks were successful, the callback will be passed the result of the successful task, Callback returns the return value of the successful task

It runs each task in series but stops whenever any of the functions were successful. Test which is successful

async.tryEach([ function getDataFromFirstWebsite(callback) { // Try getting the data from the first website callback(err, data);  }, function getDataFromSecondWebsite(callback) { // First website failed, // Try getting the data from the backup website callback(err, data);  } ], // optional callback function(err, results) { Now do something with the data. });Copy the code

4.2. Race (Which finishes first)

Run an array of task functions in parallel, and the main callback will be called as soon as any one completes or passes an error message. Equivalent to Promise. Race ()

async.race([ function(callback) { setTimeout(function() { callback(null, 'one'); }, 200); }, function(callback) {setTimeout(function() {callback(null, 'two'); }], // The result will be equal to 'two' as it finishes earlier});Copy the code

Compose (composing multiple asynchronous functions in series returns a new function similar to f(g(h()))))

Combine f(),g() and h() asynchronous functions into the form f(g(h())

Each function consumes the return value of the function that follows

Note the order of execution, where add1mul3 is mul3 followed by add1

function add1(n, callback) {
  setTimeout(function () {
    callback(null, n + 1);
  }, 10);
}

function mul3(n, callback) {
  setTimeout(function () {
    callback(null, n * 3);
  }, 10);
}

var add1mul3 = async.compose(mul3, add1); // 1) add1() 2) mul3()
add1mul3(4, function (err, result) {
  console.log(result); // 15
});
Copy the code

4.4 seq

Each function consumes the return value of the previous function. Similar to compose

pp.get('/cats', function(request, response) { var User = request.models.User; async.seq( _.bind(User.get, User), // 'User.get' has signature (id, callback(err, data)) function(user, fn) { user.getCats(fn); // 'getCats' has signature (callback(err, data)) } )(req.session.user_id, function (err, cats) { if (err) { console.error(err); response.json({ status: 'error', message: err.message }); } else { response.json({ status: 'ok', message: 'Cats found', data: cats }); }}); });Copy the code

4.5. Apply (prebind parameters to functions)

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

4.6. applyEach

async.applyEach([enableSearch, updateSchema], 'bucket', callback);
Copy the code

4.7. applyEachSeries

only a single async operation at a time.

4.8. Queue (Serial message queues)

It is a serial message queue, which no longer executes all at once by limiting the number of workers. When the number of workers is insufficient, the newly added task will queue up until a new worker is available

If all workers are in progress, the task is queued until one becomes available

Queue (worker, concurrency) Concurrency is used to define the number of workers

let q = async.queue(function (task, callback) { console.log('deal with ' + task.url); setTimeout(() => { axios({ methods: 'get', url: task.url }).then((d) => { console.log(d.data.length); callback(); }); }, 2000); }, 1); q.drain = function () { console.log('all done'); } q.push({ url: 'http://www.baidu.com' }, function (err) { if (err) { console.log(err); }}); q.unshift([{ url: 'http://www.baidu.com' }, { url: 'http://www.sogou.com' }], function (err) { if (err) { console.log(err); }}); // deal with http://www.sogou.com // 22430 // deal with http://www.baidu.com // 112041 // deal with http://www.baidu.com  // 112220 // all doneCopy the code

4.9. PriorityQueue (worker, concurrency)

Unlike queue, push can set priority push(Task, priority, [callback]).

4.10. Cargo (serial message queues responsible for one set of tasks at a time)

While queue passes only one task to one of a group of workers at a time, Cargo passes an array of tasks to a single worker, repeating when the Worker is finished. Cargo, on the other hand, is a worker responsible for a set of tasks.

// create a cargo object with payload 2
var cargo = async.cargo(function(tasks, callback) {
    for (var i=0; i<tasks.length; i++) {
        console.log('hello ' + tasks[i].name);
    }
    callback();
}, 2);

// add some items
cargo.push({name: 'foo'}, function(err) {
    console.log('finished processing foo');
});
cargo.push({name: 'bar'}, function(err) {
    console.log('finished processing bar');
});
cargo.push({name: 'baz'}, function(err) {
    console.log('finished processing baz');
});
Copy the code

4.11. nextTick ()

The browser uses setImmediate

Calls callback on a later loop around the event loop

var call_order = []; async.nextTick(function () { call_order.push('two'); // 4 console.log(call_order); }); setTimeout(() => { call_order.push('four'); // 7 console.log(call_order); }, 100); async.nextTick(function () { call_order.push('three'); // 5 console.log(call_order); }); console.log(call_order); // 1 call_order.push('one'); // 2 console.log(call_order); // 3 async.setImmediate(function (a, b, c) { console.log(a, b, c); }, 1, 2, 3);Copy the code

4.12. Asyncify (Synchronous function converted to asynchronous function)

Direct pass synchronization method:

Async.waterfall ([async.apply(fs.readfile, './ d.son ', "utf8"), async.asyncify(json.parse), // Sync function (data, waterfall) Next) {// async console.log(data) // data... next(data) // passing data...}], (data) => {console.log(data); // data... });Copy the code

Wrapping a layer of functions:

Async. Waterfall ([async asyncify (function () {/ / synchronization function according to the asynchronous function incoming parameters need to use a layer of the function and return the results to return Fs.readfilesync ('./ d.son ', "utf8")}), function (data, next) {// Perform callback and call next console.log(data.length) next(data)}, async.asyncify(JSON.parse), function (data, next) { console.log(data) next(data) } ], (data) => { console.log(data); });Copy the code

4.13. Constant (generally used to pass values to the next stage of a serial process)

The asyncify example can be modified to:

Async.waterfall ([async.constant('./ d.son ', 'utf8')), // Set parameter fs.readFile, // invoke parameter function (data, next) { console.log(data.length) next(data) }, async.asyncify(JSON.parse), function (data, next) { console.log(data) next(data) } ], (data) => { console.log(data); });Copy the code

4.14. dir (call console.dir)

Logs the result of an async function to the console using console.dir to display the properties of the resulting object. Note Browser compatibility Console. dir applies to FireFox and Chrome

// in a module
var hello = function(name, callback) {
    setTimeout(function() {
        callback(null, {hello: name});
    }, 1000);
};

// in the node repl
node> async.dir(hello, 'world');
{hello: 'world'}
Copy the code

4.15. EnsureAsync (Ensure that tasks are executed asynchronously)

function sometimesAsync(arg, callback) {
    if (cache[arg]) {
        return callback(null, cache[arg]); // this would be synchronous!!
    } else {
        doSomeIO(arg, callback); // this IO would be asynchronous
    }
}

// this has a risk of stack overflows if many results are cached in a row
async.mapSeries(args, sometimesAsync, done);

// this will defer sometimesAsync's callback if necessary,
// preventing stack overflows
async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
Copy the code

4.16. log (call console.log)

// in a module
var hello = function(name, callback) {
    setTimeout(function() {
        callback(null, 'hello ' + name);
    }, 1000);
};

// in the node repl
node> async.log(hello, 'world');
'hello world'
Copy the code

4.17. Memoize (Caching results)

Caches the results of an async function. When creating a hash to store function results against, the callback is omitted from the hash and an optional hash function can be used.

var slow_fn = function(name, callback) {
    // do something
    callback(null, result);
};
var fn = async.memoize(slow_fn);

// fn can now be used as if it were slow_fn
fn('some name', function() {
    // callback
});
Copy the code

Such as:

var slow_fn = function (url, callback) {
    axios({ methods: 'get', url }).then(e => {
        console.log(e.status)
        callback(null, e.data)
    })
};
var fn = async.memoize(slow_fn);

fn('http://baidu.com', function (e, data) {
    console.dir('done')
});
fn('http://sogou.com', function (e, data) {
    console.dir('done')
});
// 200
// 'done'
// 200
// 'done'
Copy the code

4.18. unmemoize

Undoes a memoized function, reverting it to the original

4.19. nextTick

var call_order = [];
async.nextTick(function() {
    call_order.push('two');
    // call_order now equals ['one','two']
});
call_order.push('one');

async.setImmediate(function (a, b, c) {
    // a, b, and c equal 1, 2, and 3
}, 1, 2, 3);
Copy the code

4.20. Reflect (Continue on error)

always completes with a result object, even when it errors.

async.parallel([ async.reflect(function(callback) { // do some stuff ... callback(null, 'one');  }), async.reflect(function(callback) { // do some more stuff but error ... callback('bad stuff happened');  }), async.reflect(function(callback) { // do some more stuff ... callback(null, 'two');  }) ], // optional callback function(err, results) { // values // results[0].value = 'one' // results[1].error = 'bad stuff happened' // results[2].value = 'two' });Copy the code

Such as:

async.parallel([
    async.reflect((callback) => {
        setTimeout(() => {
            callback('error')
        }, 1000)
    }),
    (callback) => {
        setTimeout(() => {
            callback(null, 'data')
        }, 2000)
    }
], (err, result) => {
    if (err) {
        console.error(err)
    } else {
        console.dir(result) // [ { error: 'error' }, 'data' ]
    }
})
Copy the code

4.21. ReflectAll (wrap reflectAll)

A helper function that wraps an array or an object of functions with reflect.

let tasks = [ function(callback) { setTimeout(function() { callback(null, 'one'); }, 200);  }, function(callback) { // do some more stuff but error ... callback(new Error('bad stuff happened'));  }, function(callback) { setTimeout(function() { callback(null, 'two'); }, 100); } ]; Async. Parallel (async. ReflectAll (tasks), // reflectAll contains tasks task list // Optional callback function(err, results) { // values // results[0].value = 'one' // results[1].error = Error('bad stuff happened') // results[2].value =  'two' });Copy the code

4.22. SetImmediate (Equivalent to setTimeout(callback, 0))

var call_order = [];
async.nextTick(function() {
    call_order.push('two');
    // call_order now equals ['one','two']
});
call_order.push('one');

async.setImmediate(function (a, b, c) {
    // a, b, and c equal 1, 2, and 3
}, 1, 2, 3);
Copy the code

4.23. Timeout (Limit the maximum delay of asynchronous function timeout, return error after time)

Sets a time limit on an asynchronous function.

If the function does not call its callback within the specified milliseconds, it will be called with a timeout error. Error returned over time: ‘ETIMEDOUT’

function getData(url, callback) { axios({ methods: 'get', url }).then(d => { setTimeout(() => { return callback(null, d.status) }, 1000); }) } let wrappeed = async.timeout(getData, 1000) wrappeed('http://baidu.com', (err, data) => { if (err) { console.log(err) } else { console.log(data) } }) // { Error: Callback function "getData" timed out. // at Timeout.timeoutCallback [as _onTimeout] (/ Users/apple/test/node_modules / _async @ server @ async/dist/async js: 4916-26) / / ats ontimeout (timers. Js: 386:14) / / ats tryOnTimeout (timers.js:250:5) // at Timer.listOnTimeout (timers.js:214:5) code: 'ETIMEDOUT' }Copy the code