如何使一个单独的同步函数等待另一个异步函数?

How to make a separate a sync function wait for another async function?

提问人:captaincustard 提问时间:7/14/2021 更新时间:7/14/2021 访问量:1575

问:

我无法在另一个异步函数中回调异步函数。 我在控制台中收到此消息:

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 返回的,因为我可以在返回之前控制台.log它,并且可以在 callForecasrAPI 中获取之前返回它。 提前感谢您的任何建议。

javascript 异步 async-await promise ecmascript-2017

评论

0赞 Hector Marin 7/14/2021
您是否尝试过将 await 关键字放入 calForecastApi 函数中?async function callForecastAPI(weatherObj) { await weatherObj; const response = await fetch('calling API'); const weatherForecast = await response.json(); return weatherForecast; }
0赞 captaincustard 7/14/2021
@HectorMarin:你说得对。我正在评论某人的回答,试图澄清为什么会这样。如果你能插话,我将不胜感激。
0赞 Lennholm 7/14/2021
@captaincustard async-await 只是 promise 的语法糖,是一种更好的编码方式。它不会神奇地使异步进程像同步一样运行,因为这需要在等待结果时阻塞运行 JS 的整个线程......或某种形式的时间旅行。

答:

1赞 jfriend00 7/14/2021 #1

如果你试图调用它并将其实际结果传递给另一个函数,那么你必须这样做。它是一个函数,所有函数都返回一个 promise。函数中的返回值将成为 promise 的解析值。因此,要从 promise 中获取值,可以使用 或 .callWeatherAPI()awaitasyncasyncasyncawait.then()

callForecastAPI(await callWeatherAPI(processSearchInput(searchInput)));

当然,这意味着此代码本身需要位于函数内部,以便您可以使用 .asyncawait

有关函数如何始终返回 promise 的更多信息,请参阅为什么我需要等待异步函数,而该函数不应该返回 Promise?async

并且,也是 并且还返回一个承诺,因此要获得实际的预测结果,您还需要使用 或 on that。callForecastAPI()asyncawait.then()

const forecast = await callForecastAPI(await callWeatherAPI(processSearchInput(searchInput)));

或者,也许使用中间变量会更清楚:

const weather = await callWeatherAPI(processSearchInput(searchInput));
const forecast = await callForecastAPI(weather);
console.log(forecast);

评论

0赞 captaincustard 7/14/2021
buy 不会 callWeatherAPI 本身等待自己的 fetch 和 json() 才能返回任何内容?如果它自己等待,为什么我必须要求另一个函数等待它?根据您提供的答案,这是否意味着“天气”,即使它已经分配给了 response.json() 的“等待”结果,仍然是一个承诺,仍然需要解决?!所以,在函数体中,我有 2 件事要等待(fetch 和 .json),然后我必须等待函数本身?!
0赞 jfriend00 7/14/2021
@captaincustard - 请阅读我在答案中链接的其他答案。它与异步函数的工作原理有关,这在另一篇文章中进行了解释。而且,你需要明白这一点。我在这个答案的第一段中也对此进行了解释。异步函数 ALL 返回一个 promise。
0赞 jfriend00 7/14/2021
@captaincustard - 重申我上面链接的另一个答案中的内容,当一个函数命中函数内部的第一个函数时,它会立即暂停该函数的执行,然后返回一个未解析的 promise。调用方只是获取未解析的承诺并继续执行。一段时间后,当您等待的 promise 解析时,该函数将继续执行,当它命中语句时,您返回的值将成为之前返回的 promise 的解析值。asyncawaitreturn
0赞 jfriend00 7/14/2021
@captaincustard - 因此,在一个函数中实际上是“设置我们已经返回的 promise 的解析值”并解析该 promise。该函数很久以前就返回了承诺。return xasyncxasync
0赞 captaincustard 7/14/2021
谢谢。我知道。但是,如果你能澄清你的陈述:“然后返回一个未解决的承诺”?我收到的信息是“已实现”。我以为一个承诺如果不得到解决,就无法实现。