异步/等待承诺挂起错误

14
我可以帮您进行翻译。以下是需要翻译的内容:

我在处理 promise 错误时遇到了一些问题。最初我的函数就是这样设置的,一切都很顺利,没有任何问题。

原始代码:

const request = require("request-promise");
async () => {
  const URL_HIDDEN = "...";

  let info = await request(URL_HIDDEN);
  info = JSON.parse(info).response.players[0];

  let playtime = await request(URL_HIDDEN);
  playtime = JSON.parse(playtime).response.games;

  console.log(info);
  console.log(playtime);
}

这是一个简化版本,但基本上我只是从Steam API请求信息。两个变量都可以打印出所有数据,没有任何问题,但一旦进行下面的重构,情况就会改变。
重构后:
const middleware = require("../middleware");
async () => {
  const URL_HIDDEN = "...";

  let requests = middleware.requestURI(URL_HIDDEN);
  console.log(requests);
}

我开始把所有的请求处理都放在一个单独的函数和文件中。

const request = require("request-promise");
middlewareObj.requestURI = async (URL_HIDDEN) => {
  console.log("1");
  let info = await request(URL_HIDDEN);
  info = JSON.parse(info).response.players[0];

  console.log("2");

  let playtime = await request(URL_HIDDEN);
  playtime = JSON.parse(playtime).response.games;

  console.log("3");

  return [{ info }, { playtime }];
};

一旦我整理好所有的变量,我希望返回一个数组。然而,一旦执行,我会在控制台上看到这个输出。
1
Promise { <pending> }
2
3

任何想法为什么重构后它会打印出“promise pending”?在原始版本中,它可以完美地打印出所有内容。

1
不是记录实际在数组中的内容,而是只打印出承诺待定。每个变量在数组中都有很多信息。 - Phil
1
因为requestURI是异步的,当执行console.log(requests)时还没有完成。 - Ivan
2
可能是如何从异步调用中返回响应?的重复问题。 - Liam
1
是的,我理解它的含义,但那不是我要找的输出。在原始代码中,它会打印出数据,在我的重构版本中,我只是将其移动到一个不同的函数中来处理请求,然后返回数据数组。我在每个请求处使用 await,所以我有点困惑出了什么问题。 - Phil
1
在你的“重构”代码中,你是否忘记在“let requests = middleware.requestURI(URL_HIDDEN);”中加上一个“await”?如果没有“await”,“requests”将是一个未决承诺。 - Jaromanda X
显示剩余6条评论
1个回答

25

在你的“重构”代码中 -

let requests = middleware.requestURI(URL_HIDDEN);

如果没有 awaitrequests 将会是一个挂起的 Promise - 因此,你需要使用它

let requests = await middleware.requestURI(URL_HIDDEN);

进一步解释,任何被标记为async的函数将返回一个Promise。

async function foo() {
    return true;
}

像这样调用

let bar = foo();
// here bar = pending promise of foo()

将结果放在 Promise 中

像这样调用它

let bar = await foo(); 
// here bar == true

有点类似(但远远不相等)于

foo().then(bar => {
    // here bar == true
})

async/await可以使已经通过Promise简化的代码变得更加简单 - 在这个人为构造的例子中,虽然并不明显


我没有意识到必须在被调用来处理请求的函数上声明await。好知道。 - Phil
1
进一步解释,任何带有async标记的函数将返回一个Promise对象。这句话真救了我(哈哈)。我不确定官方文档是否有类似的解释,但我从未遇到过如此简单明了的解释。虽然这很有道理,但以前从未被告知。 - Matt
@Matt - 这是有文献记录的 - 但你说得对,相对较少提到。 - Jaromanda X

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接