Javascript - 在从函数返回之前等待异步调用完成,不使用回调
Javascript - wait for async call to finish before returning from function, without the use of callbacks
我想先说我已经查看了很多关于这个主题的 Whosebug 问题,但我还没有找到任何 'duplicates' 本身,因为其中 none 包含解决方案解决这个具体案例。
我主要查看了 How do I return the response from an asynchronous call?,'Promises with async/await' 部分将在异步函数内运行,但我正在处理的函数不是异步的,而是现有函数的一部分我无法轻易更改的代码库。我将无法将函数更改为异步。
关于回调的部分也不起作用,这将在下面进一步解释。无论如何,我会进入我的问题:
我正在通过添加异步函数调用在 JavaScript 中编辑一个函数(标准函数,非异步函数)。我想等到异步调用完成后再从函数中 return (因为异步调用的结果需要包含在 return 值中)。我该怎么做?
我研究了使用回调,这将允许我编写保证仅在异步调用完成后 运行 的代码。但是,这不会中断原函数中的程序流程,并且原函数在回调运行之前仍然可以return。回调将允许我在异步函数之后按顺序执行某些操作,但它不允许我在最高级别等待异步调用完成。
示例代码,它不会return 想要的结果:
function getPlayers() {
... other code ...
let outfieldPlayers = asyncGetOutfieldPlayersCall()
... other code ...
allPlayers.add(outfieldPlayers)
return allPlayers // the returned value may or may not include outfield players
}
我面临的实际问题有点复杂 - 我在 for 循环的每次迭代中调用异步函数,需要等到所有调用都完成后才能 returning。但是,我想如果我能解决这个更简单的问题,我可以用for循环解决问题。
遗憾的是,几乎不可能以同步方式等待异步代码。这是因为 JS 中没有线程(大多数 JS 运行 次,但 some are 次)。所以代码要么是同步的,要么是异步的。
由于事件循环,异步代码成为可能。事件循环是 javascript 运行time 的一部分。它的工作原理是保留一堆回调函数,当 事件 触发它们时 运行 - 通常是超时事件(您可以使用 setTimeout()
设置)或 IO 事件(这在您发出磁盘或 HTTP 请求或用户交互时发生)。但是,这些回调只在运行没有其他代码运行ning的时候,所以只有在程序空闲的时候all ] 功能已经返回。
这意味着像 "spin loops" 这样的技术(你只是 运行 一个循环,直到条件被另一个线程改变)在线程环境中工作不起作用,因为异步代码不会' t 运行 直到自旋循环结束。
更多信息:https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4
如果您使用的是 NodeJS,可以通过 execSync。
这需要您将异步代码放在一个单独的文件中,使用 execSync
生成一个单独的进程,该进程将一直等到它退出。
例如,考虑以下打印数组的异步函数。
// task.js
(async function() {
await new Promise((resolve) => setTimeout(() => {
console.log(JSON.stringify([3,4,5]));
resolve();
}, 1000));
})();
现在,您可以从主进程中调用它:
function asyncGetOutfieldPlayersCall() {
const execSync = require('child_process').execSync;
return JSON.parse(execSync("node task.js"));
}
function getPlayers() {
let allPlayers = [1,2];
// ... other code ...
let outfieldPlayers = asyncGetOutfieldPlayersCall();
// ... other code ...
allPlayers = allPlayers.concat(outfieldPlayers)
return allPlayers;
}
我想先说我已经查看了很多关于这个主题的 Whosebug 问题,但我还没有找到任何 'duplicates' 本身,因为其中 none 包含解决方案解决这个具体案例。
我主要查看了 How do I return the response from an asynchronous call?,'Promises with async/await' 部分将在异步函数内运行,但我正在处理的函数不是异步的,而是现有函数的一部分我无法轻易更改的代码库。我将无法将函数更改为异步。
关于回调的部分也不起作用,这将在下面进一步解释。无论如何,我会进入我的问题:
我正在通过添加异步函数调用在 JavaScript 中编辑一个函数(标准函数,非异步函数)。我想等到异步调用完成后再从函数中 return (因为异步调用的结果需要包含在 return 值中)。我该怎么做?
我研究了使用回调,这将允许我编写保证仅在异步调用完成后 运行 的代码。但是,这不会中断原函数中的程序流程,并且原函数在回调运行之前仍然可以return。回调将允许我在异步函数之后按顺序执行某些操作,但它不允许我在最高级别等待异步调用完成。
示例代码,它不会return 想要的结果:
function getPlayers() {
... other code ...
let outfieldPlayers = asyncGetOutfieldPlayersCall()
... other code ...
allPlayers.add(outfieldPlayers)
return allPlayers // the returned value may or may not include outfield players
}
我面临的实际问题有点复杂 - 我在 for 循环的每次迭代中调用异步函数,需要等到所有调用都完成后才能 returning。但是,我想如果我能解决这个更简单的问题,我可以用for循环解决问题。
遗憾的是,几乎不可能以同步方式等待异步代码。这是因为 JS 中没有线程(大多数 JS 运行 次,但 some are 次)。所以代码要么是同步的,要么是异步的。
由于事件循环,异步代码成为可能。事件循环是 javascript 运行time 的一部分。它的工作原理是保留一堆回调函数,当 事件 触发它们时 运行 - 通常是超时事件(您可以使用 setTimeout()
设置)或 IO 事件(这在您发出磁盘或 HTTP 请求或用户交互时发生)。但是,这些回调只在运行没有其他代码运行ning的时候,所以只有在程序空闲的时候all ] 功能已经返回。
这意味着像 "spin loops" 这样的技术(你只是 运行 一个循环,直到条件被另一个线程改变)在线程环境中工作不起作用,因为异步代码不会' t 运行 直到自旋循环结束。
更多信息:https://medium.com/front-end-weekly/javascript-event-loop-explained-4cd26af121d4
如果您使用的是 NodeJS,可以通过 execSync。
这需要您将异步代码放在一个单独的文件中,使用 execSync
生成一个单独的进程,该进程将一直等到它退出。
例如,考虑以下打印数组的异步函数。
// task.js
(async function() {
await new Promise((resolve) => setTimeout(() => {
console.log(JSON.stringify([3,4,5]));
resolve();
}, 1000));
})();
现在,您可以从主进程中调用它:
function asyncGetOutfieldPlayersCall() {
const execSync = require('child_process').execSync;
return JSON.parse(execSync("node task.js"));
}
function getPlayers() {
let allPlayers = [1,2];
// ... other code ...
let outfieldPlayers = asyncGetOutfieldPlayersCall();
// ... other code ...
allPlayers = allPlayers.concat(outfieldPlayers)
return allPlayers;
}