如何使单独的同步功能等待另一个异步功能?

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 xasync 函数中实际上是“设置我们已经返回给x 的承诺的解析值”并解决该承诺。 async 函数很久以前就返回了承诺。 非常感谢。我知道了。但是,如果你能澄清你的陈述:“然后返回一个未解决的承诺”?我收到的消息说“已完成”。我认为如果没有解决,承诺就无法实现。

以上是关于如何使单独的同步功能等待另一个异步功能?的主要内容,如果未能解决你的问题,请参考以下文章

js注意事项4(同步异步)

同步和异步 各是啥啊。能举例说明吗?

使用Task.Wait而不是等待异步编程

如何使 segue 等待功能在按钮按下时完成?

同步和异步的区别是啥

java中异步处理和同步处理分别是啥意思?