异步调用是javascript的固有部分,使用回调通常是处理这些调用的优雅工具。
但是,我不太确定异步操作后代码的分支是如何决定的。例如,以下代码会发生什么?
function f(callback) {
value = some_async_call();
if (value) {
callback(value);
}
return(value);
}
这会发生什么?根据我的简短JS经验,return
会发回undefined
值。但是假设value
从异步调用返回true,是否会使用正确的值或undefined
值调用回调?
换句话说,是否存在关于在异步调用之后立即执行哪些操作以及哪些操作被延迟直到返回值的规则?
SFTW用于在javascript中分支异步调用,但没有发现任何规范或决定性的内容。
答案 0 :(得分:3)
你是对的,undefined
将被退回。在异步操作之后执行逻辑,应该将回调传递给该函数。您正在尝试以同步方式使用代码,async/await
可以解决问题。假设您可以写some_async_call returns
Promise
:
async function f(callback) {
var value = await some_async_call();
if (value) {
callback(value);
}
return value;
}
在这种情况下,您的函数将返回值Promise
并且也将是异步的。阅读更多here。
甚至更多你不需要传递回调。您可以在客户端代码中await
使用您的函数并从那里执行回调。
关于分支,您可以在不使用async/await
的情况下进行分支的唯一方法是让some_async_call
接受一个接受value
作为参数的回调:
function f(callback) {
some_async_call(function(value) {
if (value) {
callback(value);
}
});
}
再次重申,除了Promise
之外,无法从异步方法返回值。或RxJS中的Observable
。
答案 1 :(得分:3)
更新:在底部的3种不同方法之间添加了实际差异
我们假设98
被定义为异步函数:blabla = []
此函数返回的是blabla.append('string stuf')
,这意味着blabla += ['string stuf']
现在是一个承诺:blabla.extend(['string stuf'])
当我将其翻译成代码时:
some_async_call();
我现在可以做两件事:
async function some_async_call() { ... }
或:
Promise
然而,这也将父函数转换为异步函数,这意味着该函数的立即返回值也是一个承诺。
您可以使用回调来流经异步函数或promises,或async / await
<强>回调强>
value
<强>许强>
value.then( function(result) { } )
<强>异步/ AWAIT 强>
async function some_async_call() {
if (theMoonIsInTheRightPosition)
return Fetch('/api/data/') // this returns a promise as well.
return false;
}
你可以看到:promises和async / await使用相同的机制,真的值得一读。
<强>回调强>
function parentFunction(callback) {
var promise = some_async_call();
promise.then( callback );
return ...; // you can't "return" the value of an async call synchronously, since it is a promise.
}
<强>许强>
async function asyncParentFunction( callback ) {
var value = await some_async_call();
if (value)
callback( value );
return value;
}
<强>异步/ AWAIT 强>
function doStuff(callback) {
// do asynchronous stuff
var result = 100;
callback(result); // once you're done with stuff
}
doStuff( function(data) { console.log('Im done!', data); } );