Async 是一个实用模块,它提供了用于异步 JavaScript 的直接、强大的函数。虽然最初设计用于 Node.js 并可通过 npm install --save async
安装,但它也可以直接在浏览器中使用。
- 源代码:
- 参见:
Async 是一个实用模块,它提供了用于异步 JavaScript 的直接、强大的函数。虽然最初设计用于 Node.js 并可通过 npm install --save async
安装,但它也可以直接在浏览器中使用。
import concat from 'async/concat';
将 iteratee
应用于 coll
中的每个项目,连接结果。返回连接列表。iteratee
并行调用,结果在返回时连接起来。结果数组将按照传递给 iteratee
函数的 coll
的原始顺序返回。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为 Promise
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// dir4 does not exist
let directoryList = ['dir1','dir2','dir3'];
let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4'];
// Using callbacks
async.concat(directoryList, fs.readdir, function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
// [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
}
});
// Error Handling
async.concat(withMissingDirectoryList, fs.readdir, function(err, results) {
if (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4 does not exist
} else {
console.log(results);
}
});
// Using Promises
async.concat(directoryList, fs.readdir)
.then(results => {
console.log(results);
// [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
}).catch(err => {
console.log(err);
});
// Error Handling
async.concat(withMissingDirectoryList, fs.readdir)
.then(results => {
console.log(results);
}).catch(err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4 does not exist
});
// Using async/await
async () => {
try {
let results = await async.concat(directoryList, fs.readdir);
console.log(results);
// [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
} catch (err) {
console.log(err);
}
}
// Error Handling
async () => {
try {
let results = await async.concat(withMissingDirectoryList, fs.readdir);
console.log(results);
} catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4 does not exist
}
}
import concatLimit from 'async/concatLimit';
与 concat
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为 Promise
import concatSeries from 'async/concatSeries';
与 concat
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为 Promise
import detect from 'async/detect';
返回 coll
中通过异步真值测试的第一个值。iteratee
是并行应用的,这意味着第一个返回 true
的迭代器将使用该结果触发检测 callback
。这意味着结果可能不是原始 coll
(按顺序)中通过测试的第一个项目。
如果原始 coll
中的顺序很重要,请查看 detectSeries
。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 对 |
callback |
function <可选> | 任何 iteratee 返回 |
如果省略回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// asynchronous function that checks if a file exists
function fileExists(file, callback) {
fs.access(file, fs.constants.F_OK, (err) => {
callback(null, !err);
});
}
async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists,
function(err, result) {
console.log(result);
// dir1/file1.txt
// result now equals the first file in the list that exists
}
);
// Using Promises
async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists)
.then(result => {
console.log(result);
// dir1/file1.txt
// result now equals the first file in the list that exists
}).catch(err => {
console.log(err);
});
// Using async/await
async () => {
try {
let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists);
console.log(result);
// dir1/file1.txt
// result now equals the file in the list that exists
}
catch (err) {
console.log(err);
}
}
import detectLimit from 'async/detectLimit';
与 detect
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 对 |
callback |
function <可选> | 任何 iteratee 返回 |
如果省略回调,则为承诺
import detectSeries from 'async/detectSeries';
与 detect
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 对 |
callback |
function <可选> | 任何 iteratee 返回 |
如果省略回调,则为承诺
import each from 'async/each';
将函数 iteratee
并行应用于 coll
中的每个项目。使用列表中的项目调用 iteratee
,并在完成后回调。如果 iteratee
将错误传递给其 callback
,则立即使用错误调用主 callback
(用于 each
函数)。
请注意,由于此函数将 iteratee
并行应用于每个项目,因此不能保证 iteratee 函数将按顺序完成。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// dir4 does not exist
const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt'];
const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt'];
// asynchronous function that deletes a file
const deleteFile = function(file, callback) {
fs.unlink(file, callback);
};
// Using callbacks
async.each(fileList, deleteFile, function(err) {
if( err ) {
console.log(err);
} else {
console.log('All files have been deleted successfully');
}
});
// Error Handling
async.each(withMissingFileList, deleteFile, function(err){
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4/file2.txt does not exist
// dir1/file1.txt could have been deleted
});
// Using Promises
async.each(fileList, deleteFile)
.then( () => {
console.log('All files have been deleted successfully');
}).catch( err => {
console.log(err);
});
// Error Handling
async.each(fileList, deleteFile)
.then( () => {
console.log('All files have been deleted successfully');
}).catch( err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4/file2.txt does not exist
// dir1/file1.txt could have been deleted
});
// Using async/await
async () => {
try {
await async.each(files, deleteFile);
}
catch (err) {
console.log(err);
}
}
// Error Handling
async () => {
try {
await async.each(withMissingFileList, deleteFile);
}
catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
// since dir4/file2.txt does not exist
// dir1/file1.txt could have been deleted
}
}
import eachLimit from 'async/eachLimit';
与 each
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
import eachOf from 'async/eachOf';
与 each
类似,不同之处在于它将键(或索引)作为第二个参数传递给 iteratee。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
// dev.json is a file containing a valid json object config for dev environment
// dev.json is a file containing a valid json object config for test environment
// prod.json is a file containing a valid json object config for prod environment
// invalid.json is a file with a malformed json object
let configs = {}; //global variable
let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'};
let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'};
// asynchronous function that reads a json file and parses the contents as json object
function parseFile(file, key, callback) {
fs.readFile(file, "utf8", function(err, data) {
if (err) return calback(err);
try {
configs[key] = JSON.parse(data);
} catch (e) {
return callback(e);
}
callback();
});
}
// Using callbacks
async.forEachOf(validConfigFileMap, parseFile, function (err) {
if (err) {
console.error(err);
} else {
console.log(configs);
// configs is now a map of JSON data, e.g.
// { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
}
});
//Error handing
async.forEachOf(invalidConfigFileMap, parseFile, function (err) {
if (err) {
console.error(err);
// JSON parse error exception
} else {
console.log(configs);
}
});
// Using Promises
async.forEachOf(validConfigFileMap, parseFile)
.then( () => {
console.log(configs);
// configs is now a map of JSON data, e.g.
// { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
}).catch( err => {
console.error(err);
});
//Error handing
async.forEachOf(invalidConfigFileMap, parseFile)
.then( () => {
console.log(configs);
}).catch( err => {
console.error(err);
// JSON parse error exception
});
// Using async/await
async () => {
try {
let result = await async.forEachOf(validConfigFileMap, parseFile);
console.log(configs);
// configs is now a map of JSON data, e.g.
// { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
}
catch (err) {
console.log(err);
}
}
//Error handing
async () => {
try {
let result = await async.forEachOf(invalidConfigFileMap, parseFile);
console.log(configs);
}
catch (err) {
console.log(err);
// JSON parse error exception
}
}
import eachOfLimit from 'async/eachOfLimit';
与 eachOf
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
import eachOfSeries from 'async/eachOfSeries';
与 eachOf
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
import eachSeries from 'async/eachSeries';
与 each
相同,但一次只运行一个异步操作。
请注意,与 each
不同,此函数将 iteratee 串联应用于每个项目,因此 iteratee 函数将按顺序完成。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果省略回调,则为承诺
import every from 'async/every';
如果 coll
中的每个元素都满足异步测试,则返回 true
。如果任何 iteratee 调用返回 false
,则立即调用主 callback
。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 一个异步真值测试,并行应用于集合中的每个项目。迭代器必须使用布尔结果值完成。使用 (item, callback) 调用。 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// dir4 does not exist
const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt'];
const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
// asynchronous function that checks if a file exists
function fileExists(file, callback) {
fs.access(file, fs.constants.F_OK, (err) => {
callback(null, !err);
});
}
// Using callbacks
async.every(fileList, fileExists, function(err, result) {
console.log(result);
// true
// result is true since every file exists
});
async.every(withMissingFileList, fileExists, function(err, result) {
console.log(result);
// false
// result is false since NOT every file exists
});
// Using Promises
async.every(fileList, fileExists)
.then( result => {
console.log(result);
// true
// result is true since every file exists
}).catch( err => {
console.log(err);
});
async.every(withMissingFileList, fileExists)
.then( result => {
console.log(result);
// false
// result is false since NOT every file exists
}).catch( err => {
console.log(err);
});
// Using async/await
async () => {
try {
let result = await async.every(fileList, fileExists);
console.log(result);
// true
// result is true since every file exists
}
catch (err) {
console.log(err);
}
}
async () => {
try {
let result = await async.every(withMissingFileList, fileExists);
console.log(result);
// false
// result is false since NOT every file exists
}
catch (err) {
console.log(err);
}
}
import everyLimit from 'async/everyLimit';
与 every
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 一个异步真值测试,并行应用于集合中的每个项目。迭代器必须使用布尔结果值完成。使用 (item, callback) 调用。 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
import everySeries from 'async/everySeries';
与 every
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 一个异步真值测试,串行应用于集合中的每个项目。迭代器必须使用布尔结果值完成。使用 (item, callback) 调用。 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
import filter from 'async/filter';
返回 coll
中通过异步真值测试的所有值的新数组。此操作是并行执行的,但结果数组的顺序与原始数组相同。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
function | 对 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
// asynchronous function that checks if a file exists
function fileExists(file, callback) {
fs.access(file, fs.constants.F_OK, (err) => {
callback(null, !err);
});
}
// Using callbacks
async.filter(files, fileExists, function(err, results) {
if(err) {
console.log(err);
} else {
console.log(results);
// [ 'dir1/file1.txt', 'dir2/file3.txt' ]
// results is now an array of the existing files
}
});
// Using Promises
async.filter(files, fileExists)
.then(results => {
console.log(results);
// [ 'dir1/file1.txt', 'dir2/file3.txt' ]
// results is now an array of the existing files
}).catch(err => {
console.log(err);
});
// Using async/await
async () => {
try {
let results = await async.filter(files, fileExists);
console.log(results);
// [ 'dir1/file1.txt', 'dir2/file3.txt' ]
// results is now an array of the existing files
}
catch (err) {
console.log(err);
}
}
import filterLimit from 'async/filterLimit';
与 filter
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
function | 对 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
import filterSeries from 'async/filterSeries';
与 filter
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
function | 对 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
import groupBy from 'async/groupBy';
返回一个新对象,其中每个值对应于来自 coll
的项目数组,该数组返回相应的键。也就是说,对象的键对应于传递给 iteratee
回调的值。
注意:由于此函数将 iteratee
并行应用于每个项目,因此不能保证 iteratee
函数将按顺序完成。但是,result
中每个键的值将与原始 coll
的顺序相同。对于对象,值将大致按照原始对象的键的顺序排列(但这在 JavaScript 引擎之间可能有所不同)。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果没有传递回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// dir4 does not exist
const files = ['dir1/file1.txt','dir2','dir4']
// asynchronous function that detects file type as none, file, or directory
function detectFile(file, callback) {
fs.stat(file, function(err, stat) {
if (err) {
return callback(null, 'none');
}
callback(null, stat.isDirectory() ? 'directory' : 'file');
});
}
//Using callbacks
async.groupBy(files, detectFile, function(err, result) {
if(err) {
console.log(err);
} else {
console.log(result);
// {
// file: [ 'dir1/file1.txt' ],
// none: [ 'dir4' ],
// directory: [ 'dir2']
// }
// result is object containing the files grouped by type
}
});
// Using Promises
async.groupBy(files, detectFile)
.then( result => {
console.log(result);
// {
// file: [ 'dir1/file1.txt' ],
// none: [ 'dir4' ],
// directory: [ 'dir2']
// }
// result is object containing the files grouped by type
}).catch( err => {
console.log(err);
});
// Using async/await
async () => {
try {
let result = await async.groupBy(files, detectFile);
console.log(result);
// {
// file: [ 'dir1/file1.txt' ],
// none: [ 'dir4' ],
// directory: [ 'dir2']
// }
// result is object containing the files grouped by type
}
catch (err) {
console.log(err);
}
}
import groupByLimit from 'async/groupByLimit';
与 groupBy
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果没有传递回调,则为承诺
import groupBySeries from 'async/groupBySeries';
与 groupBy
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 所有 |
如果没有传递回调,则为承诺
import map from 'async/map';
通过将 coll
中的每个值映射到 iteratee
函数来生成一个新的值集合。iteratee
会使用来自 coll
的一个项和处理完成后的回调来调用。每个回调都需要 2 个参数:error
和来自 coll
的转换项。如果 iteratee
将错误传递给其回调,则主 callback
(用于 map
函数)会立即使用错误调用。
请注意,由于此函数将 iteratee
并行应用于每个项目,因此不能保证 iteratee
函数将按顺序完成。但是,结果数组的顺序将与原始 coll
相同。
如果 map
传递了一个对象,则结果将是一个数组。结果将大致按照原始对象的键的顺序排列(但这可能因 JavaScript 引擎而异)。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
// file1.txt is a file that is 1000 bytes in size
// file2.txt is a file that is 2000 bytes in size
// file3.txt is a file that is 3000 bytes in size
// file4.txt does not exist
const fileList = ['file1.txt','file2.txt','file3.txt'];
const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
// asynchronous function that returns the file size in bytes
function getFileSizeInBytes(file, callback) {
fs.stat(file, function(err, stat) {
if (err) {
return callback(err);
}
callback(null, stat.size);
});
}
// Using callbacks
async.map(fileList, getFileSizeInBytes, function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
// results is now an array of the file size in bytes for each file, e.g.
// [ 1000, 2000, 3000]
}
});
// Error Handling
async.map(withMissingFileList, getFileSizeInBytes, function(err, results) {
if (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
} else {
console.log(results);
}
});
// Using Promises
async.map(fileList, getFileSizeInBytes)
.then( results => {
console.log(results);
// results is now an array of the file size in bytes for each file, e.g.
// [ 1000, 2000, 3000]
}).catch( err => {
console.log(err);
});
// Error Handling
async.map(withMissingFileList, getFileSizeInBytes)
.then( results => {
console.log(results);
}).catch( err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
});
// Using async/await
async () => {
try {
let results = await async.map(fileList, getFileSizeInBytes);
console.log(results);
// results is now an array of the file size in bytes for each file, e.g.
// [ 1000, 2000, 3000]
}
catch (err) {
console.log(err);
}
}
// Error Handling
async () => {
try {
let results = await async.map(withMissingFileList, getFileSizeInBytes);
console.log(results);
}
catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
}
}
import mapLimit from 'async/mapLimit';
与 map
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
import mapSeries from 'async/mapSeries';
与 map
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
import mapValues from 'async/mapValues';
map
的相对项,设计用于对象。
通过将 obj
中的每个值映射到 iteratee
函数来生成一个新的对象。iteratee
会从 obj
调用每个 value
和 key
,并在处理完成后回调。每个回调都需要两个参数:error
和来自 obj
的转换项。如果 iteratee
将错误传递给其回调,则主 callback
(用于 mapValues
函数)会立即使用错误调用。
请注意,结果中键的顺序无法保证。键将大致按照它们完成的顺序排列(但这非常特定于引擎)
名称 | 类型 | 描述 |
---|---|---|
obj |
Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
// file1.txt is a file that is 1000 bytes in size
// file2.txt is a file that is 2000 bytes in size
// file3.txt is a file that is 3000 bytes in size
// file4.txt does not exist
const fileMap = {
f1: 'file1.txt',
f2: 'file2.txt',
f3: 'file3.txt'
};
const withMissingFileMap = {
f1: 'file1.txt',
f2: 'file2.txt',
f3: 'file4.txt'
};
// asynchronous function that returns the file size in bytes
function getFileSizeInBytes(file, key, callback) {
fs.stat(file, function(err, stat) {
if (err) {
return callback(err);
}
callback(null, stat.size);
});
}
// Using callbacks
async.mapValues(fileMap, getFileSizeInBytes, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
// result is now a map of file size in bytes for each file, e.g.
// {
// f1: 1000,
// f2: 2000,
// f3: 3000
// }
}
});
// Error handling
async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) {
if (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
} else {
console.log(result);
}
});
// Using Promises
async.mapValues(fileMap, getFileSizeInBytes)
.then( result => {
console.log(result);
// result is now a map of file size in bytes for each file, e.g.
// {
// f1: 1000,
// f2: 2000,
// f3: 3000
// }
}).catch (err => {
console.log(err);
});
// Error Handling
async.mapValues(withMissingFileMap, getFileSizeInBytes)
.then( result => {
console.log(result);
}).catch (err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
});
// Using async/await
async () => {
try {
let result = await async.mapValues(fileMap, getFileSizeInBytes);
console.log(result);
// result is now a map of file size in bytes for each file, e.g.
// {
// f1: 1000,
// f2: 2000,
// f3: 3000
// }
}
catch (err) {
console.log(err);
}
}
// Error Handling
async () => {
try {
let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes);
console.log(result);
}
catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
}
}
import mapValuesLimit from 'async/mapValuesLimit';
与 mapValues
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
obj |
Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
import mapValuesSeries from 'async/mapValuesSeries';
与 mapValues
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
obj |
Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function <可选> | 当所有 |
如果没有传递回调,则为承诺
import reduce from 'async/reduce';
使用异步 iteratee
将 coll
简化为单个值以返回每个连续步骤。 memo
是归约的初始状态。此函数仅串联操作。
出于性能原因,将此函数的调用拆分为并行映射,然后在结果上使用正常的 Array.prototype.reduce
可能是有意义的。此功能适用于减少中每个步骤都需要异步的情况;如果你可以在减少数据之前获取数据,那么这样做可能是一个好主意。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
memo |
* | 归约的初始状态。 |
iteratee |
AsyncFunction | 应用于数组中每个项目的函数,以产生缩减的下一步。 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为承诺
// file1.txt is a file that is 1000 bytes in size
// file2.txt is a file that is 2000 bytes in size
// file3.txt is a file that is 3000 bytes in size
// file4.txt does not exist
const fileList = ['file1.txt','file2.txt','file3.txt'];
const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
// asynchronous function that computes the file size in bytes
// file size is added to the memoized value, then returned
function getFileSizeInBytes(memo, file, callback) {
fs.stat(file, function(err, stat) {
if (err) {
return callback(err);
}
callback(null, memo + stat.size);
});
}
// Using callbacks
async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
// 6000
// which is the sum of the file sizes of the three files
}
});
// Error Handling
async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
if (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
} else {
console.log(result);
}
});
// Using Promises
async.reduce(fileList, 0, getFileSizeInBytes)
.then( result => {
console.log(result);
// 6000
// which is the sum of the file sizes of the three files
}).catch( err => {
console.log(err);
});
// Error Handling
async.reduce(withMissingFileList, 0, getFileSizeInBytes)
.then( result => {
console.log(result);
}).catch( err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
});
// Using async/await
async () => {
try {
let result = await async.reduce(fileList, 0, getFileSizeInBytes);
console.log(result);
// 6000
// which is the sum of the file sizes of the three files
}
catch (err) {
console.log(err);
}
}
// Error Handling
async () => {
try {
let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
console.log(result);
}
catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
}
}
import reduceRight from 'async/reduceRight';
与 reduce
相同,仅以相反的顺序对 array
进行操作。
名称 | 类型 | 描述 |
---|---|---|
array |
Array | 要迭代的集合。 |
memo |
* | 归约的初始状态。 |
iteratee |
AsyncFunction | 应用于数组中每个项目的函数,以产生缩减的下一步。 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为承诺
import reject from 'async/reject';
filter
的反面。删除通过 async
真值测试的值。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
function | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
// asynchronous function that checks if a file exists
function fileExists(file, callback) {
fs.access(file, fs.constants.F_OK, (err) => {
callback(null, !err);
});
}
// Using callbacks
async.reject(fileList, fileExists, function(err, results) {
// [ 'dir3/file6.txt' ]
// results now equals an array of the non-existing files
});
// Using Promises
async.reject(fileList, fileExists)
.then( results => {
console.log(results);
// [ 'dir3/file6.txt' ]
// results now equals an array of the non-existing files
}).catch( err => {
console.log(err);
});
// Using async/await
async () => {
try {
let results = await async.reject(fileList, fileExists);
console.log(results);
// [ 'dir3/file6.txt' ]
// results now equals an array of the non-existing files
}
catch (err) {
console.log(err);
}
}
import rejectLimit from 'async/rejectLimit';
与 reject
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
function | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为承诺
import rejectSeries from 'async/rejectSeries';
与 reject
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
function | 应用于 |
callback |
function <可选> | 在所有 |
如果没有传递回调,则为承诺
import some from 'async/some';
如果 coll
中至少有一个元素满足异步测试,则返回 true
。如果任何 iteratee 调用返回 true
,则立即调用主 callback
。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 一个异步真值测试,并行应用于集合中的每个项目。迭代器应使用布尔 |
callback |
function <可选> | 任何 iteratee 返回 |
如果没有提供回调,则为承诺
// dir1 is a directory that contains file1.txt, file2.txt
// dir2 is a directory that contains file3.txt, file4.txt
// dir3 is a directory that contains file5.txt
// dir4 does not exist
// asynchronous function that checks if a file exists
function fileExists(file, callback) {
fs.access(file, fs.constants.F_OK, (err) => {
callback(null, !err);
});
}
// Using callbacks
async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists,
function(err, result) {
console.log(result);
// true
// result is true since some file in the list exists
}
);
async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists,
function(err, result) {
console.log(result);
// false
// result is false since none of the files exists
}
);
// Using Promises
async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists)
.then( result => {
console.log(result);
// true
// result is true since some file in the list exists
}).catch( err => {
console.log(err);
});
async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists)
.then( result => {
console.log(result);
// false
// result is false since none of the files exists
}).catch( err => {
console.log(err);
});
// Using async/await
async () => {
try {
let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists);
console.log(result);
// true
// result is true since some file in the list exists
}
catch (err) {
console.log(err);
}
}
async () => {
try {
let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists);
console.log(result);
// false
// result is false since none of the files exists
}
catch (err) {
console.log(err);
}
}
import someLimit from 'async/someLimit';
与 some
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 一个异步真值测试,并行应用于集合中的每个项目。迭代器应使用布尔 |
callback |
function <可选> | 任何 iteratee 返回 |
如果没有提供回调,则为承诺
import someSeries from 'async/someSeries';
与 some
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 一个异步真值测试,串行应用于集合中的每个项目。迭代器应使用布尔 |
callback |
function <可选> | 任何 iteratee 返回 |
如果没有提供回调,则为承诺
import sortBy from 'async/sortBy';
根据通过异步 iteratee
运行每个 coll
值的结果对列表进行排序。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
iteratee |
AsyncFunction | 应用于 |
callback |
function | 在所有 |
如果没有传递回调,则为承诺
// bigfile.txt is a file that is 251100 bytes in size
// mediumfile.txt is a file that is 11000 bytes in size
// smallfile.txt is a file that is 121 bytes in size
// asynchronous function that returns the file size in bytes
function getFileSizeInBytes(file, callback) {
fs.stat(file, function(err, stat) {
if (err) {
return callback(err);
}
callback(null, stat.size);
});
}
// Using callbacks
async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes,
function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
// results is now the original array of files sorted by
// file size (ascending by default), e.g.
// [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
}
}
);
// By modifying the callback parameter the
// sorting order can be influenced:
// ascending order
async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) {
getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
if (getFileSizeErr) return callback(getFileSizeErr);
callback(null, fileSize);
});
}, function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
// results is now the original array of files sorted by
// file size (ascending by default), e.g.
// [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
}
}
);
// descending order
async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) {
getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
if (getFileSizeErr) {
return callback(getFileSizeErr);
}
callback(null, fileSize * -1);
});
}, function(err, results) {
if (err) {
console.log(err);
} else {
console.log(results);
// results is now the original array of files sorted by
// file size (ascending by default), e.g.
// [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt']
}
}
);
// Error handling
async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes,
function(err, results) {
if (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
} else {
console.log(results);
}
}
);
// Using Promises
async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes)
.then( results => {
console.log(results);
// results is now the original array of files sorted by
// file size (ascending by default), e.g.
// [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
}).catch( err => {
console.log(err);
});
// Error handling
async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes)
.then( results => {
console.log(results);
}).catch( err => {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
});
// Using async/await
(async () => {
try {
let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
console.log(results);
// results is now the original array of files sorted by
// file size (ascending by default), e.g.
// [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
}
catch (err) {
console.log(err);
}
})();
// Error handling
async () => {
try {
let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
console.log(results);
}
catch (err) {
console.log(err);
// [ Error: ENOENT: no such file or directory ]
}
}
import transform from 'async/transform';
reduce
的相对项。接受对象或数组,并并行迭代每个元素,每个步骤都可能改变 accumulator
值。累加器的类型默认为传入的集合类型。
名称 | 类型 | 描述 |
---|---|---|
coll |
Array | Iterable | AsyncIterable | Object | 要迭代的集合。 |
accumulator |
* <可选> | 变换的初始状态。如果省略,它将默认为空对象或数组,具体取决于 |
iteratee |
AsyncFunction | 应用于集合中每个项目的函数,可能会修改累加器。使用 (accumulator, item, key, callback) 调用。 |
callback |
function <可选> | 在所有 |
如果没有提供回调,则为承诺
// file1.txt is a file that is 1000 bytes in size
// file2.txt is a file that is 2000 bytes in size
// file3.txt is a file that is 3000 bytes in size
// helper function that returns human-readable size format from bytes
function formatBytes(bytes, decimals = 2) {
// implementation not included for brevity
return humanReadbleFilesize;
}
const fileList = ['file1.txt','file2.txt','file3.txt'];
// asynchronous function that returns the file size, transformed to human-readable format
// e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
function transformFileSize(acc, value, key, callback) {
fs.stat(value, function(err, stat) {
if (err) {
return callback(err);
}
acc[key] = formatBytes(stat.size);
callback(null);
});
}
// Using callbacks
async.transform(fileList, transformFileSize, function(err, result) {
if(err) {
console.log(err);
} else {
console.log(result);
// [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
}
});
// Using Promises
async.transform(fileList, transformFileSize)
.then(result => {
console.log(result);
// [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
}).catch(err => {
console.log(err);
});
// Using async/await
(async () => {
try {
let result = await async.transform(fileList, transformFileSize);
console.log(result);
// [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
}
catch (err) {
console.log(err);
}
})();
// file1.txt is a file that is 1000 bytes in size
// file2.txt is a file that is 2000 bytes in size
// file3.txt is a file that is 3000 bytes in size
// helper function that returns human-readable size format from bytes
function formatBytes(bytes, decimals = 2) {
// implementation not included for brevity
return humanReadbleFilesize;
}
const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' };
// asynchronous function that returns the file size, transformed to human-readable format
// e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
function transformFileSize(acc, value, key, callback) {
fs.stat(value, function(err, stat) {
if (err) {
return callback(err);
}
acc[key] = formatBytes(stat.size);
callback(null);
});
}
// Using callbacks
async.transform(fileMap, transformFileSize, function(err, result) {
if(err) {
console.log(err);
} else {
console.log(result);
// { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
}
});
// Using Promises
async.transform(fileMap, transformFileSize)
.then(result => {
console.log(result);
// { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
}).catch(err => {
console.log(err);
});
// Using async/await
async () => {
try {
let result = await async.transform(fileMap, transformFileSize);
console.log(result);
// { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
}
catch (err) {
console.log(err);
}
}
import applyEach from 'async/applyEach';
将提供的参数应用于数组中的每个函数,在所有函数完成后调用 callback
。如果你只提供第一个参数 fns
,那么它将返回一个函数,该函数允许你传入参数,就像它是单个函数调用一样。如果提供了更多参数,则 callback
是必需的,而 args
仍然是可选的。每个应用的异步函数的结果都作为数组传递给最终回调。
名称 | 类型 | 描述 |
---|---|---|
fns |
Array | Iterable | AsyncIterable | Object | 所有使用相同参数调用的 AsyncFunction 集合 |
args |
* <可选> | 传递给函数的任意数量的单独参数。 |
callback |
function <可选> | 最后一个参数应该是回调函数,当所有函数都完成处理时调用。 |
args
应用于每个函数的结果。const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket')
appliedFn((err, results) => {
// results[0] is the results for `enableSearch`
// results[1] is the results for `updateSchema`
});
// partial application example:
async.each(
buckets,
async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(),
callback
);
import applyEachSeries from 'async/applyEachSeries';
与 applyEach
相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
fns |
Array | Iterable | AsyncIterable | Object | 所有使用相同参数调用的 AsyncFunction 集合 |
args |
* <可选> | 传递给函数的任意数量的单独参数。 |
callback |
function <可选> | 最后一个参数应该是回调函数,当所有函数都完成处理时调用。 |
args
应用于函数列表的结果。除了回调之外,它不需要任何参数。import auto from 'async/auto';
根据其要求确定在 tasks
中运行 AsyncFunction 的最佳顺序。每个函数都可以选择依赖于首先完成的其他函数,并且每个函数都会在其要求得到满足后立即运行。
如果任何 AsyncFunction 向其回调传递错误,auto
序列将停止。进一步的任务将不会执行(因此任何依赖于它的其他函数都不会运行),并且主 callback
会立即被调用并出现错误。
如果它们具有依赖,AsyncFunction 还会接收一个包含迄今为止已完成的函数结果的对象作为第一个参数。如果任务函数没有依赖,则只会传递一个回调。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
tasks |
Object | 一个对象。它的每个属性都是一个函数或一个需求数组,AsyncFunction 本身是数组中的最后一项。对象的属性的键用作该属性定义的任务的名称,即可以在指定其他任务的要求时使用。该函数接收一个或两个参数:* |
|
concurrency |
number <可选> | Infinity | 可选 |
callback |
function <可选> | 可选回调,当所有任务都完成后调用。如果任何 |
如果没有传递回调,则为承诺
//Using Callbacks
async.auto({
get_data: function(callback) {
// async code to get some data
callback(null, 'data', 'converted to array');
},
make_folder: function(callback) {
// async code to create a directory to store a file in
// this is run at the same time as getting the data
callback(null, 'folder');
},
write_file: ['get_data', 'make_folder', function(results, callback) {
// once there is some data and the directory exists,
// write the data to a file in the directory
callback(null, 'filename');
}],
email_link: ['write_file', function(results, callback) {
// once the file is written let's email a link to it...
callback(null, {'file':results.write_file, 'email':'user@example.com'});
}]
}, function(err, results) {
if (err) {
console.log('err = ', err);
}
console.log('results = ', results);
// results = {
// get_data: ['data', 'converted to array']
// make_folder; 'folder',
// write_file: 'filename'
// email_link: { file: 'filename', email: 'user@example.com' }
// }
});
//Using Promises
async.auto({
get_data: function(callback) {
console.log('in get_data');
// async code to get some data
callback(null, 'data', 'converted to array');
},
make_folder: function(callback) {
console.log('in make_folder');
// async code to create a directory to store a file in
// this is run at the same time as getting the data
callback(null, 'folder');
},
write_file: ['get_data', 'make_folder', function(results, callback) {
// once there is some data and the directory exists,
// write the data to a file in the directory
callback(null, 'filename');
}],
email_link: ['write_file', function(results, callback) {
// once the file is written let's email a link to it...
callback(null, {'file':results.write_file, 'email':'user@example.com'});
}]
}).then(results => {
console.log('results = ', results);
// results = {
// get_data: ['data', 'converted to array']
// make_folder; 'folder',
// write_file: 'filename'
// email_link: { file: 'filename', email: 'user@example.com' }
// }
}).catch(err => {
console.log('err = ', err);
});
//Using async/await
async () => {
try {
let results = await async.auto({
get_data: function(callback) {
// async code to get some data
callback(null, 'data', 'converted to array');
},
make_folder: function(callback) {
// async code to create a directory to store a file in
// this is run at the same time as getting the data
callback(null, 'folder');
},
write_file: ['get_data', 'make_folder', function(results, callback) {
// once there is some data and the directory exists,
// write the data to a file in the directory
callback(null, 'filename');
}],
email_link: ['write_file', function(results, callback) {
// once the file is written let's email a link to it...
callback(null, {'file':results.write_file, 'email':'user@example.com'});
}]
});
console.log('results = ', results);
// results = {
// get_data: ['data', 'converted to array']
// make_folder; 'folder',
// write_file: 'filename'
// email_link: { file: 'filename', email: 'user@example.com' }
// }
}
catch (err) {
console.log(err);
}
}
import autoInject from 'async/autoInject';
async.auto 函数的依赖注入版本。依赖任务被指定为函数的参数,位于通常的回调参数之后,参数名称与其依赖的任务名称相匹配。这可以提供更易读的任务图,从而更易于维护。 如果指定了最终回调,则任务结果将以类似的方式注入,在初始错误参数后指定为命名参数。 autoInject 函数纯粹是语法糖,其语义在其他方面等同于 async.auto。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Object | 一个对象,其每个属性都是 'func([dependencies...], callback). The object' 形式的 AsyncFunction,属性的键用作该属性定义的任务的名称,即可以在指定其他任务的要求时使用。 * |
callback |
function <可选> | 可选回调,当所有任务都完成后调用。如果任何 |
如果没有传递回调,则为承诺
// The example from `auto` can be rewritten as follows:
async.autoInject({
get_data: function(callback) {
// async code to get some data
callback(null, 'data', 'converted to array');
},
make_folder: function(callback) {
// async code to create a directory to store a file in
// this is run at the same time as getting the data
callback(null, 'folder');
},
write_file: function(get_data, make_folder, callback) {
// once there is some data and the directory exists,
// write the data to a file in the directory
callback(null, 'filename');
},
email_link: function(write_file, callback) {
// once the file is written let's email a link to it...
// write_file contains the filename returned by write_file.
callback(null, {'file':write_file, 'email':'user@example.com'});
}
}, function(err, results) {
console.log('err = ', err);
console.log('email_link = ', results.email_link);
});
// If you are using a JS minifier that mangles parameter names, `autoInject`
// will not work with plain functions, since the parameter names will be
// collapsed to a single letter identifier. To work around this, you can
// explicitly specify the names of the parameters your task function needs
// in an array, similar to Angular.js dependency injection.
// This still has an advantage over plain `auto`, since the results a task
// depends on are still spread into arguments.
async.autoInject({
//...
write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
callback(null, 'filename');
}],
email_link: ['write_file', function(write_file, callback) {
callback(null, {'file':write_file, 'email':'user@example.com'});
}]
//...
}, function(err, results) {
console.log('err = ', err);
console.log('email_link = ', results.email_link);
});
import cargo from 'async/cargo';
使用指定的有效负载创建 cargo
对象。添加到货物中的任务将被一起处理(最多 payload
限制)。如果 worker
正在进行中,则任务将排队,直到可用。一旦 worker
完成了一些任务,就会调用这些任务的每个回调。查看 these animations 了解 cargo
和 queue
的工作原理。
虽然 queue
一次只将一个任务传递给一组工作者中的一个,但 cargo 会将一组任务传递给单个工作者,并在工作者完成时重复。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
worker |
AsyncFunction | 一个用于处理排队任务数组的异步函数。使用 |
|
payload |
number <可选> | Infinity | 可选 |
一个用于管理任务的货物对象。回调可以作为某些属性附加,以在货物和内部队列的生命周期中监听特定事件。
// 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');
});
await cargo.push({name: 'baz'});
console.log('finished processing baz');
import cargoQueue from 'async/cargoQueue';
使用指定的有效负载创建 cargoQueue
对象。添加到 cargoQueue 的任务将在 concurrency
并行工作器中一起处理(最多 payload
限制)。如果所有 workers
都在进行中,则任务将排队,直到其中一个可用。一旦 worker
完成了一些任务,就会调用这些任务的每个回调。查看 these animations 了解 cargo
和 queue
的工作原理。
虽然 queue
一次只将一个任务传递给一组工作者中的一个,而 cargo
一次将一组任务传递给单个工作者,但 cargoQueue 会将一组任务传递给多个并行工作者。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
worker |
AsyncFunction | 一个用于处理排队任务数组的异步函数。使用 |
|
concurrency |
number <可选> | 1 | 用于确定应并行运行多少个 |
payload |
number <可选> | Infinity | 可选 |
一个用于管理任务的货物队列对象。回调可以作为某些属性附加,以在货物队列和内部队列的生命周期中监听特定事件。
// create a cargoQueue object with payload 2 and concurrency 2
var cargoQueue = async.cargoQueue(function(tasks, callback) {
for (var i=0; i<tasks.length; i++) {
console.log('hello ' + tasks[i].name);
}
callback();
}, 2, 2);
// add some items
cargoQueue.push({name: 'foo'}, function(err) {
console.log('finished processing foo');
});
cargoQueue.push({name: 'bar'}, function(err) {
console.log('finished processing bar');
});
cargoQueue.push({name: 'baz'}, function(err) {
console.log('finished processing baz');
});
cargoQueue.push({name: 'boo'}, function(err) {
console.log('finished processing boo');
});
async.cargo
import compose from 'async/compose';
创建一个由传递的异步函数组成的函数。每个函数都会使用后面函数的返回值。组合函数 f()
、g()
和 h()
会产生 f(g(h()))
的结果,只有此版本使用回调来获取返回值。
如果组合函数的最后一个参数不是函数,则调用它时会返回一个承诺。
每个函数都使用组合函数的 this
绑定执行。
名称 | 类型 | 描述 |
---|---|---|
functions |
AsyncFunction | 要编写的异步函数 |
由异步 functions
组成的异步函数
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);
add1mul3(4, function (err, result) {
// result now equals 15
});
import doUntil from 'async/doUntil';
类似于 'doWhilst',但 test
是反转的。请注意,参数顺序与 until
不同。
名称 | 类型 | 描述 |
---|---|---|
iteratee |
AsyncFunction | 每次 |
test |
AsyncFunction | 每次执行 |
callback |
function <可选> | 在测试函数通过且 |
如果没有传递回调,则为承诺
import doWhilst from 'async/doWhilst';
whilst
的后检查版本。为了反映操作顺序的差异,参数 test
和 iteratee
被切换。
doWhilst
与 whilst
的关系就像纯 JavaScript 中的 do while
与 while
的关系一样。
名称 | 类型 | 描述 |
---|---|---|
iteratee |
AsyncFunction | 每次 |
test |
AsyncFunction | 每次执行 |
callback |
function <可选> | 在测试函数失败且 |
如果没有传递回调,则为承诺
import forever from 'async/forever';
使用回调参数调用异步函数 fn
,该回调参数允许它无限期地再次串行调用自身。
如果将错误传递给回调,则使用错误调用 errback
,并停止执行,否则将永远不会被调用。
名称 | 类型 | 描述 |
---|---|---|
fn |
AsyncFunction | 要重复调用的异步函数。使用 (next) 调用。 |
errback |
function <可选> | 当 |
如果发生错误且未传递错误回调,则为拒绝的承诺
async.forever(
function(next) {
// next is suitable for passing to things that need a callback(err [, whatever]);
// it will result in this function being called again.
},
function(err) {
// if next is called with a value in its first parameter, it will appear
// in here as 'err', and execution will stop.
}
);
import parallel from 'async/parallel';
并行运行 tasks
函数集合,而无需等到上一个函数完成。如果任何函数将错误传递给其回调,则立即使用错误值调用主 callback
。一旦 tasks
完成,结果将作为数组传递给最终的 callback
。
注意:parallel
是关于并行启动 I/O 任务,而不是并行执行代码。如果你的任务不使用任何计时器或执行任何 I/O,它们实际上将按顺序执行。每个任务的任何同步设置部分都将一个接一个地发生。JavaScript 仍然是单线程的。
**提示:**当任务失败时,使用 reflect
继续执行其他任务。
也可以使用对象而不是数组。每个属性都将作为函数运行,结果将作为对象而不是数组传递给最终的 callback
。这是一种处理 async.parallel 结果的更具可读性的方式。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | Iterable | AsyncIterable | Object | 要运行的 异步函数 集合。每个异步函数都可以使用任意数量的可选 |
callback |
function <可选> | 所有函数成功完成后运行的可选回调。此函数获取一个结果数组(或对象),其中包含传递给任务回调的所有结果参数。使用 (err, results) 调用。 |
如果没有传递回调,则为承诺
//Using Callbacks
async.parallel([
function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
callback(null, 'two');
}, 100);
}
], function(err, results) {
console.log(results);
// results is equal to ['one','two'] even though
// the second function had a shorter timeout.
});
// an example using an object instead of an array
async.parallel({
one: function(callback) {
setTimeout(function() {
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
// results is equal to: { one: 1, two: 2 }
});
//Using Promises
async.parallel([
function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
callback(null, 'two');
}, 100);
}
]).then(results => {
console.log(results);
// results is equal to ['one','two'] even though
// the second function had a shorter timeout.
}).catch(err => {
console.log(err);
});
// an example using an object instead of an array
async.parallel({
one: function(callback) {
setTimeout(function() {
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
callback(null, 2);
}, 100);
}
}).then(results => {
console.log(results);
// results is equal to: { one: 1, two: 2 }
}).catch(err => {
console.log(err);
});
//Using async/await
async () => {
try {
let results = await async.parallel([
function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
callback(null, 'two');
}, 100);
}
]);
console.log(results);
// results is equal to ['one','two'] even though
// the second function had a shorter timeout.
}
catch (err) {
console.log(err);
}
}
// an example using an object instead of an array
async () => {
try {
let results = await async.parallel({
one: function(callback) {
setTimeout(function() {
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
callback(null, 2);
}, 100);
}
});
console.log(results);
// results is equal to: { one: 1, two: 2 }
}
catch (err) {
console.log(err);
}
}
import parallelLimit from 'async/parallelLimit';
与 parallel
相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | Iterable | AsyncIterable | Object | 要运行的 异步函数 集合。每个异步函数都可以使用任意数量的可选 |
limit |
number | 一次异步操作的最大数量。 |
callback |
function <可选> | 所有函数成功完成后运行的可选回调。此函数获取一个结果数组(或对象),其中包含传递给任务回调的所有结果参数。使用 (err, results) 调用。 |
如果没有传递回调,则为承诺
import priorityQueue from 'async/priorityQueue';
与 async.queue 相同,只有任务被分配优先级并按优先级升序完成。
名称 | 类型 | 描述 |
---|---|---|
worker |
AsyncFunction | 用于处理排队任务的异步函数。如果你想处理单个任务的错误,请将回调传递给 |
concurrency |
number | 用于确定应并行运行多少个 |
一个用于管理任务的 priorityQueue 对象。queue
和 priorityQueue
对象之间有三个区别:* push(task, priority, [callback])
- priority
应该是一个数字。如果给出了 tasks
的数组,则所有任务将被分配相同的优先级。* pushAsync(task, priority, [callback])
- 与 priorityQueue.push
相同,只不过这会返回一个如果发生错误就会拒绝的承诺。* unshift
和 unshiftAsync
方法已被删除。
import queue from 'async/queue';
Creates a queue
object with the specified concurrency
. Tasks added to the
queue
are processed in parallel (up to the concurrency
limit). If all
worker
s are in progress, the task is queued until one becomes available.
Once a worker
completes a task
, that task
's callback is called.
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
worker |
AsyncFunction | 用于处理排队任务的异步函数。如果你想处理单个任务的错误,请将回调传递给 |
|
concurrency |
number <可选> | 1 | 用于确定应并行运行多少个 |
一个用于管理任务的队列对象。回调可以作为某些属性附加,以在队列的生命周期中监听特定事件。
// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
console.log('hello ' + task.name);
callback();
}, 2);
// assign a callback
q.drain(function() {
console.log('all items have been processed');
});
// or await the end
await q.drain()
// assign an error callback
q.error(function(err, task) {
console.error('task experienced an error');
});
// add some items to the queue
q.push({name: 'foo'}, function(err) {
console.log('finished processing foo');
});
// callback is optional
q.push({name: 'bar'});
// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
console.log('finished processing item');
});
// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
console.log('finished processing bar');
});
import race from 'async/race';
并行运行 tasks
函数数组,而不等到前一个函数完成。一旦任何 tasks
完成或将错误传递给其回调,就会立即调用主 callback
。它相当于 Promise.race()
。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | 包含要运行的 异步函数 的数组。每个函数都可以使用可选的 |
callback |
function | 任何函数完成后运行的回调。此函数从第一个完成的函数获取错误或结果。使用 (err, result) 调用。 |
如果省略回调,则为承诺
async.race([
function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
callback(null, 'two');
}, 100);
}
],
// main callback
function(err, result) {
// the result will be equal to 'two' as it finishes earlier
});
import retry from 'async/retry';
在返回错误之前,尝试从 task
获取成功响应的次数不超过 times
次。如果任务成功,callback
将传递成功任务的结果。如果所有尝试都失败,回调将传递最后一次尝试的错误和结果(如果有)。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
opts |
Object | number <可选> | {times: 5, interval: 0}| 5 | 可以是具有 |
task |
AsyncFunction | 用于重试的异步函数。使用 (callback) 调用。 |
|
callback |
function <可选> | 可选回调,当任务成功或最后一次尝试失败后调用。它接收完成 |
如果没有提供回调,则为承诺
// The `retry` function can be used as a stand-alone control flow by passing
// a callback, as shown below:
// try calling apiMethod 3 times
async.retry(3, apiMethod, function(err, result) {
// do something with the result
});
// try calling apiMethod 3 times, waiting 200 ms between each retry
async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
// do something with the result
});
// try calling apiMethod 10 times with exponential backoff
// (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
async.retry({
times: 10,
interval: function(retryCount) {
return 50 * Math.pow(2, retryCount);
}
}, apiMethod, function(err, result) {
// do something with the result
});
// try calling apiMethod the default 5 times no delay between each retry
async.retry(apiMethod, function(err, result) {
// do something with the result
});
// try calling apiMethod only when error condition satisfies, all other
// errors will abort the retry control flow and return to final callback
async.retry({
errorFilter: function(err) {
return err.message === 'Temporary error'; // only retry on a specific error
}
}, apiMethod, function(err, result) {
// do something with the result
});
// to retry individual methods that are not as reliable within other
// control flow functions, use the `retryable` wrapper:
async.auto({
users: api.getUsers.bind(api),
payments: async.retryable(3, api.getPayments.bind(api))
}, function(err, results) {
// do something with the results
});
import retryable from 'async/retryable';
retry
的近亲。此方法封装任务并使其可重试,而不是立即调用它并重试。
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
opts |
Object | number <可选> | {times: 5, interval: 0}| 5 | 可选选项,与 |
task |
AsyncFunction | 要封装的异步函数。此函数将传递传递给返回封装器的任何参数。使用 (...args, callback) 调用。 |
封装函数在调用时将根据 opts
中指定的参数在发生错误时重试。此函数将接受与 task
相同的参数。
async.auto({
dep1: async.retryable(3, getFromFlakyService),
process: ["dep1", async.retryable(3, function (results, cb) {
maybeProcessData(results.dep1, cb);
})]
}, callback);
import seq from 'async/seq';
更自然阅读的 compose 函数版本。每个函数都会使用前一个函数的返回值。它相当于参数反转的 compose。
每个函数都使用组合函数的 this
绑定执行。
名称 | 类型 | 描述 |
---|---|---|
functions |
AsyncFunction | 要编写的异步函数 |
按顺序组合 functions
的函数
// Requires lodash (or underscore), express3 and dresende's orm2.
// Part of an app, that fetches cats of the logged user.
// This example uses `seq` function to avoid overnesting and error
// handling clutter.
app.get('/cats', function(request, response) {
var User = request.models.User;
async.seq(
User.get.bind(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 });
}
});
});
import series from 'async/series';
串联运行 tasks
集合中的函数,每个函数在前一个函数完成后运行。如果系列中的任何函数将错误传递给其回调,则不再运行其他函数,并立即使用错误值调用 callback
。否则,当 tasks
完成后,callback
会收到一个结果数组。
也可以使用对象而不是数组。每个属性都将作为函数运行,结果将作为对象而不是数组传递给最终的 callback
。这是一种处理 async.series 结果的更具可读性的方式。
注意,虽然许多实现都保留了对象属性的顺序,但 ECMAScript Language Specification 明确指出
未指定枚举属性的机制和顺序。 因此,如果你依赖于执行一系列函数的顺序,并希望它在所有平台上都能正常工作,请考虑使用数组。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | Iterable | AsyncIterable | Object | 包含要串联运行的 异步函数 的集合。每个函数都可以使用任意数量的可选 |
callback |
function <可选> | 所有函数完成后运行的可选回调。此函数获取一个结果数组(或对象),其中包含传递给 |
a promise, if no callback is passed
//Using Callbacks
async.series([
function(callback) {
setTimeout(function() {
// do some async task
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
// then do another async task
callback(null, 'two');
}, 100);
}
], function(err, results) {
console.log(results);
// results is equal to ['one','two']
});
// an example using objects instead of arrays
async.series({
one: function(callback) {
setTimeout(function() {
// do some async task
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
// then do another async task
callback(null, 2);
}, 100);
}
}, function(err, results) {
console.log(results);
// results is equal to: { one: 1, two: 2 }
});
//Using Promises
async.series([
function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
callback(null, 'two');
}, 100);
}
]).then(results => {
console.log(results);
// results is equal to ['one','two']
}).catch(err => {
console.log(err);
});
// an example using an object instead of an array
async.series({
one: function(callback) {
setTimeout(function() {
// do some async task
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
// then do another async task
callback(null, 2);
}, 100);
}
}).then(results => {
console.log(results);
// results is equal to: { one: 1, two: 2 }
}).catch(err => {
console.log(err);
});
//Using async/await
async () => {
try {
let results = await async.series([
function(callback) {
setTimeout(function() {
// do some async task
callback(null, 'one');
}, 200);
},
function(callback) {
setTimeout(function() {
// then do another async task
callback(null, 'two');
}, 100);
}
]);
console.log(results);
// results is equal to ['one','two']
}
catch (err) {
console.log(err);
}
}
// an example using an object instead of an array
async () => {
try {
let results = await async.parallel({
one: function(callback) {
setTimeout(function() {
// do some async task
callback(null, 1);
}, 200);
},
two: function(callback) {
setTimeout(function() {
// then do another async task
callback(null, 2);
}, 100);
}
});
console.log(results);
// results is equal to: { one: 1, two: 2 }
}
catch (err) {
console.log(err);
}
}
import times from 'async/times';
调用 iteratee
函数 n
次,并以与使用 map 相同的方式累积结果。
名称 | 类型 | 描述 |
---|---|---|
n |
number | 运行该函数的次数。 |
iteratee |
AsyncFunction | 要调用 |
callback |
function | 参见 map。 |
如果没有提供回调,则为承诺
// Pretend this is some complicated async factory
var createUser = function(id, callback) {
callback(null, {
id: 'user' + id
});
};
// generate 5 users
async.times(5, function(n, next) {
createUser(n, function(err, user) {
next(err, user);
});
}, function(err, users) {
// we should now have 5 users
});
import timesLimit from 'async/timesLimit';
与 times 相同,但一次最多运行 limit
个异步操作。
名称 | 类型 | 描述 |
---|---|---|
count |
number | 运行该函数的次数。 |
limit |
number | 一次异步操作的最大数量。 |
iteratee |
AsyncFunction | 要调用 |
callback |
function | 参见 async.map。 |
如果没有提供回调,则为承诺
import timesSeries from 'async/timesSeries';
与 times 相同,但一次只运行一个异步操作。
名称 | 类型 | 描述 |
---|---|---|
n |
number | 运行该函数的次数。 |
iteratee |
AsyncFunction | 要调用 |
callback |
function | 参见 map。 |
如果没有提供回调,则为承诺
import tryEach from 'async/tryEach';
它按顺序运行每个任务,但只要任何函数成功就会停止。如果其中一个任务成功,callback
将传递成功任务的结果。如果所有任务都失败,回调将传递最后一次尝试的错误和结果(如果有)。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | Iterable | AsyncIterable | Object | 包含要运行的函数的集合,每个函数都会传递一个 |
callback |
function <可选> | 可选回调,当其中一个任务成功或所有任务都失败时调用。它接收完成 |
如果没有传递回调,则为承诺
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.
});
import until from 'async/until';
重复调用 iteratee
,直到 test
返回 true
。停止或发生错误时调用 callback
。callback
将传递错误,并将任何参数传递给最终 iteratee
的回调。
whilst 的逆。
名称 | 类型 | 描述 |
---|---|---|
test |
AsyncFunction | 每次执行 |
iteratee |
AsyncFunction | 每次 |
callback |
function <可选> | 在测试函数通过且 |
如果没有传递回调,则为承诺
const results = []
let finished = false
async.until(function test(cb) {
cb(null, finished)
}, function iter(next) {
fetchPage(url, (err, body) => {
if (err) return next(err)
results = results.concat(body.objects)
finished = !!body.next
next(err)
})
}, function done (err) {
// all pages have been fetched
})
import waterfall from 'async/waterfall';
串联运行 tasks
函数数组,每个函数将其结果传递给数组中的下一个。但是,如果任何 tasks
将错误传递给它们自己的回调,则不会执行下一个函数,并且会立即调用主 callback
并显示错误。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | 要运行的 异步函数 数组。每个函数应使用任意数量的 |
callback |
function <可选> | 所有函数完成后运行的可选回调。这将传递最后一个任务回调的结果。使用 (err, [results]) 调用。 |
如果省略回调,则为承诺
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'
});
// Or, with named functions:
async.waterfall([
myFirstFunction,
mySecondFunction,
myLastFunction,
], function (err, result) {
// result now equals 'done'
});
function myFirstFunction(callback) {
callback(null, 'one', 'two');
}
function mySecondFunction(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
}
function myLastFunction(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
import whilst from 'async/whilst';
重复调用 iteratee
,而 test
返回 true
。停止或发生错误时调用 callback
。
名称 | 类型 | 描述 |
---|---|---|
test |
AsyncFunction | 每次执行 |
iteratee |
AsyncFunction | 每次 |
callback |
function <可选> | 在测试函数失败且 |
如果没有传递回调,则为承诺
var count = 0;
async.whilst(
function test(cb) { cb(null, count < 5); },
function iter(callback) {
count++;
setTimeout(function() {
callback(null, count);
}, 1000);
},
function (err, n) {
// 5 seconds have passed, n = 5
}
);
import queue from 'async/queue';
工作函数要完成的任务队列。
Name | Type | Description |
---|---|---|
length |
function | a function returning the number of items
waiting to be processed. Invoke with |
started |
boolean | a boolean indicating whether or not any items have been pushed and processed by the queue. |
running |
function | a function returning the number of items
currently being processed. Invoke with |
workersList |
function | a function returning the array of items
currently being processed. Invoke with |
idle |
function | a function returning false if there are items
waiting or being processed, or true if not. Invoke with |
concurrency |
number | an integer for determining how many |
payload |
number | an integer that specifies how many items are passed to the worker function at a time. only applies if this is a cargo object |
push |
AsyncFunction | add a new task to the |
unshift |
AsyncFunction | add a new task to the front of the |
pushAsync |
AsyncFunction | the same as |
unshiftAsync |
AsyncFunction | the same as |
remove |
function | remove items from the queue that match a test
function. The test function will be passed an object with a |
saturated |
function | a function that sets a callback that is
called when the number of running workers hits the |
unsaturated |
function | a function that sets a callback that is
called when the number of running workers is less than the |
buffer |
number | A minimum threshold buffer in order to say that
the |
empty |
function | a function that sets a callback that is called
when the last item from the |
drain |
function | a function that sets a callback that is called
when the last item from the |
error |
function | a function that sets a callback that is called
when a task errors. Has the signature |
paused |
boolean | a boolean for determining whether the queue is in a paused state. |
pause |
function | a function that pauses the processing of tasks
until |
resume |
function | a function that resumes the processing of
queued tasks when the queue is paused. Invoke with |
kill |
function | a function that removes the |
const q = async.queue(worker, 2)
q.push(item1)
q.push(item2)
q.push(item3)
// queues are iterable, spread into an array to inspect
const items = [...q] // [item1, item2, item3]
// or use for of
for (let item of q) {
console.log(item)
}
q.drain(() => {
console.log('all done')
})
// or
await q.drain()
import apply from 'async/apply';
创建一个已应用一些参数的延续函数。 与其他控制流函数结合使用时可用作简写。传递给返回函数的任何参数都将添加到最初传递给应用的参数中。
名称 | 类型 | 描述 |
---|---|---|
fn |
function | 你最终想要应用所有参数的函数。使用 (arguments...) 调用。 |
arguments... |
* | 在调用延续时自动应用的任意数量的参数。 |
部分应用的函数
// using apply
async.parallel([
async.apply(fs.writeFile, 'testfile1', 'test1'),
async.apply(fs.writeFile, 'testfile2', 'test2')
]);
// the same process without using apply
async.parallel([
function(callback) {
fs.writeFile('testfile1', 'test1', callback);
},
function(callback) {
fs.writeFile('testfile2', 'test2', callback);
}
]);
// It's possible to pass any number of additional arguments when calling the
// continuation:
node> var fn = async.apply(sys.puts, 'one');
node> fn('two', 'three');
one
two
three
import asyncify from 'async/asyncify';
采用同步函数并使其异步,将其返回值传递给回调。这对于将同步函数插入瀑布、系列或其他异步函数很有用。传递给生成函数的任何参数都将传递给封装函数(最后一个回调参数除外)。抛出的错误将传递给回调。
如果传递给 asyncify
的函数返回一个 Promise,则将使用该承诺的已解决/已拒绝状态来调用回调,而不仅仅是同步返回值。
这也意味着你可以异步 ES2017 async
函数。
名称 | 类型 | 描述 |
---|---|---|
func |
function | 要转换为 AsyncFunction 的同步函数或 Promise 返回函数。 |
func
的异步封装器。与 (args..., callback)
一起调用。
// passing a regular synchronous function
async.waterfall([
async.apply(fs.readFile, filename, "utf8"),
async.asyncify(JSON.parse),
function (data, next) {
// data is the result of parsing the text.
// If there was a parsing error, it would have been caught.
}
], callback);
// passing a function returning a promise
async.waterfall([
async.apply(fs.readFile, filename, "utf8"),
async.asyncify(function (contents) {
return db.model.create(contents);
}),
function (model, next) {
// `model` is the instantiated model object.
// If there was an error, this function would be skipped.
}
], callback);
// es2017 example, though `asyncify` is not needed if your JS environment
// supports async functions out of the box
var q = async.queue(async.asyncify(async function(file) {
var intermediateStep = await processFile(file);
return await somePromise(intermediateStep)
}));
q.push(files);
名称 | 类型 | 描述 |
---|---|---|
arguments... |
* | 用于自动调用回调的任意数量的参数。 |
返回一个函数,当调用时,会自动使用先前给定的参数调用回调。
async.waterfall([
async.constant(42),
function (value, next) {
// value === 42
},
//...
], callback);
async.waterfall([
async.constant(filename, "utf8"),
fs.readFile,
function (fileData, next) {
//...
}
//...
], callback);
async.auto({
hostname: async.constant("https://server.net/"),
port: findFreePort,
launchServer: ["hostname", "port", function (options, cb) {
startServer(options, cb);
}],
//...
}, callback);
import dir from 'async/dir';
使用 console.dir
将 async
函数 的结果记录到 console
,以显示结果对象的属性。仅适用于 Node.js 或支持 console.dir
和 console.error
的浏览器(例如 FF 和 Chrome)。如果异步函数返回多个参数,则按顺序对每个参数调用 console.dir
。
名称 | 类型 | 描述 |
---|---|---|
function |
AsyncFunction | 你最终想要应用所有参数的函数。 |
arguments... |
* | 应用于函数的任意数量的参数。 |
// 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'}
import ensureAsync from 'async/ensureAsync';
封装一个异步函数并确保它在事件循环的后续滴答中调用其回调。如果该函数已经在下一个滴答中调用其回调,则不会添加额外的延迟。这对于防止堆栈溢出 (RangeError: Maximum call stack size exceeded
) 和通常保持 Zalgo 不受控制非常有用。ES2017 async
函数按原样返回 - 它们不受 Zalgo 破坏影响,因为它们总是在稍后的滴答声中解析。
名称 | 类型 | 描述 |
---|---|---|
fn |
AsyncFunction | 一个异步函数,期望节点样式回调作为其最后一个参数。 |
返回一个封装函数,其调用签名与传入的函数完全相同。
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);
import log from 'async/log';
将 async
函数的结果记录到 console
。仅适用于 Node.js 或支持 console.log
和 console.error
的浏览器(例如 FF 和 Chrome)。如果异步函数返回多个参数,则按顺序对每个参数调用 console.log
。
名称 | 类型 | 描述 |
---|---|---|
function |
AsyncFunction | 你最终想要应用所有参数的函数。 |
arguments... |
* | 应用于函数的任意数量的参数。 |
// 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'
import memoize from 'async/memoize';
缓存异步函数的结果。当创建哈希来存储函数结果时,回调将从哈希中省略,并且可以使用可选的哈希函数。
注意:如果异步函数出错,结果将不会被缓存,后续调用将调用封装函数。
如果未指定哈希函数,则第一个参数将用作哈希键,如果它是字符串或转换为不同字符串的数据类型,则可能会合理地工作。请注意,对象和数组不会表现得合理。其他参数很重要的情况也是如此。在这种情况下,请指定你自己的哈希函数。
结果缓存作为 memoize
返回的函数的 memo
属性公开。
名称 | 类型 | 描述 |
---|---|---|
fn |
AsyncFunction | 用于代理和缓存结果的异步函数。 |
hasher |
function | 用于生成用于存储结果的自定义哈希的可选函数。除了回调之外,它还应用了所有参数,并且必须是同步的。 |
fn
的记忆版本
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
});
import nextTick from 'async/nextTick';
在事件循环的后续循环中调用 callback
。在 Node.js 中,这只会调用 process.nextTick
。在浏览器中,它将使用 setImmediate
(如果可用),否则使用 setTimeout(callback, 0)
,这意味着其他更高优先级的事件可能先于 callback
的执行。
这在内部用于浏览器兼容性目的。
名称 | 类型 | 描述 |
---|---|---|
callback |
function | 在事件循环的后续循环中调用的函数。使用 (args...) 调用。 |
args... |
* | 在下一个滴答声中传递给回调的任意数量的附加参数。 |
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);
import reflect from 'async/reflect';
将异步函数封装在另一个函数中,该函数始终以结果对象完成,即使出错也是如此。
结果对象具有属性 error
或 value
。
名称 | 类型 | 描述 |
---|---|---|
fn |
AsyncFunction | 要封装的异步函数 |
error
或 value
属性的 object
。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'
});
import reflectAll from 'async/reflectAll';
使用 reflect
封装函数数组或对象的辅助函数。
名称 | 类型 | 描述 |
---|---|---|
tasks |
Array | Object | Iterable | 要封装在 |
返回一个异步函数数组,每个函数都封装在 async.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),
// optional callback
function(err, results) {
// values
// results[0].value = 'one'
// results[1].error = Error('bad stuff happened')
// results[2].value = 'two'
});
// an example using an object instead of an array
let tasks = {
one: function(callback) {
setTimeout(function() {
callback(null, 'one');
}, 200);
},
two: function(callback) {
callback('two');
},
three: function(callback) {
setTimeout(function() {
callback(null, 'three');
}, 100);
}
};
async.parallel(async.reflectAll(tasks),
// optional callback
function(err, results) {
// values
// results.one.value = 'one'
// results.two.error = 'two'
// results.three.value = 'three'
});
import setImmediate from 'async/setImmediate';
在事件循环的后续循环中调用 callback
。在 Node.js 中,这只会调用 setImmediate
。在浏览器中,它将使用 setImmediate
(如果可用),否则使用 setTimeout(callback, 0)
,这意味着其他更高优先级的事件可能先于 callback
的执行。
这在内部用于浏览器兼容性目的。
名称 | 类型 | 描述 |
---|---|---|
callback |
function | 在事件循环的后续循环中调用的函数。使用 (args...) 调用。 |
args... |
* | 在下一个滴答声中传递给回调的任意数量的附加参数。 |
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);
import timeout from 'async/timeout';
为异步函数设置时间限制。如果函数未在指定的毫秒内调用其回调,则会调用它并显示超时错误。错误对象的代码属性将为 'ETIMEDOUT'
。
名称 | 类型 | 描述 |
---|---|---|
asyncFn |
AsyncFunction | 要限制时间的异步函数。 |
milliseconds |
number | 指定的时间限制。 |
info |
* <可选> | 你想要附加到超时错误的任何变量( |
返回一个可与任何控制流函数一起使用的封装函数。使用与 asyncFunc
相同的参数调用此函数。
function myFunction(foo, callback) {
doAsyncTask(foo, function(err, data) {
// handle errors
if (err) return callback(err);
// do some stuff ...
// return processed data
return callback(null, data);
});
}
var wrapped = async.timeout(myFunction, 1000);
// call `wrapped` as you would `myFunction`
wrapped({ bar: 'bar' }, function(err, data) {
// if `myFunction` takes < 1000 ms to execute, `err`
// and `data` will have their expected values
// else `err` will be an Error with the code 'ETIMEDOUT'
});
import unmemoize from 'async/unmemoize';
撤消 memoized 函数,将其恢复为原始的未记忆形式。方便测试。
名称 | 类型 | 描述 |
---|---|---|
fn |
AsyncFunction | 记忆函数 |
调用原始未记忆函数的函数