如何使单独的同步功能等待另一个异步功能?
Posted
技术标签:
【中文标题】如何使单独的同步功能等待另一个异步功能?【英文标题】:How to make a separate a sync function wait for another async function? 【发布时间】:2021-09-23 00:11:21 【问题描述】:我无法在另一个异步函数中回调异步函数。 我在控制台中收到了这个:
Promise <pending>
__proto__: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Object
script.js:127 TypeError: Cannot read property 'aWeatherObjProperty' of undefined
at callForecastAPI (script.js:121)
at htmlInputElement.<anonymous> (script.js:138)
这是我的 javascript 代码:
function processSearchInput(searchInput)
// does some math. No waiting required.
return processedSearchInput;
// processedSearchInput is an object
// Take processedSearchInput and call OpenWeather API
async function callWeatherAPI(processedSearchInput)
const response = await fetch(`calling API`, mode: 'cors' );
const weather = await response.json();
return weather;
// weather is an object
// Call OpenWeather Forecast API and return weatherForecast object
async function callForecastAPI(weatherObj)
const response = await fetch(`calling API`);
const weatherForecast = await response.json();
return weatherForecast;
callForecastAPI(callWeatherAPI(processSearchInput(searchInput)));
我确定 callWeatherAPI 正在返回天气对象,因为我可以在返回之前对其进行控制台记录,并且可以在 callForecasrAPI 中获取之前将其返回。 提前感谢您的任何建议。
【问题讨论】:
您是否尝试将 await 关键字放入您的 calForecastApi 函数中?async function callForecastAPI(weatherObj) await weatherObj; const response = await fetch('calling API'); const weatherForecast = await response.json(); return weatherForecast;
@HectorMarin:你是对的。我正在评论某人的回答,试图澄清为什么会这样。如果您能插话,我将不胜感激。
@captaincustard async-await 只是 Promise 的语法糖,是一种更好的编码方式。它不会神奇地使异步进程像同步一样运行,因为这需要在等待结果时阻塞运行 JS 的整个线程……或者某种形式的时间旅行。
【参考方案1】:
如果您尝试调用callWeatherAPI()
并将其实际结果传递给另一个函数,那么您必须将其传递给await
。这是一个async
函数,所有async
函数都返回一个promise。 async
函数中的返回值成为 promise 的解析值。因此,要从 Promise 中获取值,您可以使用 await
或 .then()
。
callForecastAPI(await callWeatherAPI(processSearchInput(searchInput)));
当然,这意味着此代码本身需要位于 async
函数中,以便您可以使用 await
。
有关async
函数如何始终返回承诺的更多信息,请参阅Why do I need to await an async function when it is not supposedly returning a Promise?。
而且,callForecastAPI()
也是 async
并且还返回一个承诺,因此要获得实际的预测结果,您也需要使用 await
或 .then()
。
const forecast = await callForecastAPI(await callWeatherAPI(processSearchInput(searchInput)));
或者,也许使用中间变量会更清楚:
const weather = await callWeatherAPI(processSearchInput(searchInput));
const forecast = await callForecastAPI(weather);
console.log(forecast);
【讨论】:
Buy 不调用WeatherAPI 本身等待自己的fetch 和json() 才能返回任何东西?如果它等待自己,为什么我必须要求另一个函数等待它?根据您提供的答案,这是否意味着“天气”,即使它已经分配给 response.json() 的“等待”结果,仍然是一个承诺,仍然需要解决?!所以,在函数体内,我有两件事要等待(fetch 和 .json),然后我必须等待函数本身?! @captaincustard - 请阅读我在答案中链接到的其他答案。它与异步函数的工作方式有关,这在另一篇文章中进行了解释。而且,您需要了解这一点。我在此答案的第一段中也对此进行了解释。异步函数都返回一个承诺。 @captaincustard - 重申我在上面链接的另一个答案中的内容,当async
函数在函数内遇到第一个 await
时,它会立即暂停该函数的执行,然后返回一个未解决的承诺。调用者只是得到未解决的承诺并继续执行。稍后,当您等待的 promise 解析时,该函数将继续执行,当它遇到 return
语句时,您返回的值将成为之前返回的 promise 的解析值。
@captaincustard - 所以,return x
在async
函数中实际上是“设置我们已经返回给x
的承诺的解析值”并解决该承诺。 async
函数很久以前就返回了承诺。
非常感谢。我知道了。但是,如果你能澄清你的陈述:“然后返回一个未解决的承诺”?我收到的消息说“已完成”。我认为如果没有解决,承诺就无法实现。以上是关于如何使单独的同步功能等待另一个异步功能?的主要内容,如果未能解决你的问题,请参考以下文章