注意:这个答案是在 2014 年写的async function
,在 Promises 出现之前,并且在 Promises 流行之前。虽然同样的原则也适用,但我建议先阅读 Promises,然后再尝试了解它们与“传统”回调驱动的异步函数的关系。
要创建一个异步调用其回调的函数,您必须在其上使用一些平台提供的异步原语(通常与 IO 相关) - 计时器、从文件系统读取、发出请求等。
例如,这个函数接受一个回调参数,并在 100 毫秒后调用它:
function asyncFn(callback) {
setTimeout(() => {
callback();
}, 100);
}
在不需要时使函数异步的一个可能原因是 API 一致性。例如,假设您有一个发出网络请求并缓存结果以供以后调用的函数:
var cache = null;
function makeRequest(callback) {
if (!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
callback(cache);
}
}
问题是,这个函数是不一致的:有时是异步的,有时不是。假设你有一个这样的消费者:
makeRequest(result => doSomethingWithResult(result));
doSomethingElse();
该doSomethingElse
函数可以在该函数之前或之后doSomethingWithResult
运行,具体取决于结果是否被缓存。现在,如果您在makeRequest
函数上使用异步原语,例如process.nextTick
:
var cache = null;
function makeRequest(callback) {
if(!cache) {
makeAjax(result => {
cache = result;
callback(result);
});
} else {
process.nextTick(() => callback(cache));
}
}
调用始终是异步的,并且doSomethingElse
始终在 之前运行doSomethingWithResult
。