【问题标题】:I can't get the value of "result" in Node.js我无法在 Node.js 中获得“结果”的值
【发布时间】:2017-05-03 08:40:25
【问题描述】:

在我的console.log(info) 中,我想获取“结果”的值。但是当我使用console.log(info) 时,我得到Promise { <pending> }

var info=new Promise((resolve, reject) => {
  request(options, (err, res, body) => {
    if (body.match('success') || body.match('code="25"')) {
      resolve("success");
    } else {
      reject(body);
    }
  });
}).then(result => {           
  return result;
}).catch(err => {
  console.log("error: " + err)
});

console.log(info);

我想得到info == result。我该怎么做?

谢谢

【问题讨论】:

  • 你需要测试你的promise以获得结果info.then(result => console.log(result)。结果准备好后,它将运行您的代码。
  • 你在使用 npm 的请求模块吗?
  • 你需要先了解 Promise 是如何工作的。它们是异步的,你不能直接从它们返回值并分配它
  • 另外,请注意您的.catch() 错误记录器正在“吃掉”错误并且不允许它传播。

标签: javascript node.js es6-promise


【解决方案1】:

在您的代码中,info 是一个承诺。因此,您不会将info 与任何东西进行比较。要在 Promise 中访问结果,请在 Promise 上使用 .then(),如下所示:

info.then(result => {
    // test result here
}).catch(err => {
    // handle error here
});

此外,您的.catch() 处理程序在记录错误后正在“吃掉”错误。如果您不重新抛出错误或从 .catch() 处理程序返回被拒绝的承诺,则错误被视为“已处理”并且承诺状态更改为已完成。

所以,你可以这样做:

let info = new Promise((resolve, reject) => {

    request(options, (err, res, body) => {
        if (body.match('success') || body.match('code="25"')) {
            resolve("success");
        } else {
            reject(body);
        }
    });
}).catch(err => {
    console.log("error: " + err);
    // rethrow error so promise stays rejected
    throw err;
});

info.then(result => {
    // test result here
}).catch(err => {
    // handle error here
});

【讨论】:

  • 非常感谢,但是如果我使用 info.then(result => { // 此处测试结果 }).catch(err => { // 此处处理错误 });我怎样才能得到我的价值结果?我真的想要一个像“let anwser=result”这样的值,我不想只在 info.then(result=>...
  • @aline5188 - 由于您可能是新来的,如果这回答了您的问题,您可以通过单击答案左侧的绿色复选标记向社区表明,这也将获得你这里有一些声望点。
  • @aline5188 - 你不能用异步操作来做到这一点。该值直到稍后的某个时间才可用,并且您可以使用它的唯一位置是在 .then() 处理程序中。这就是异步开发在 Javascript 中的工作方式,也是使用异步操作进行编程时需要学习的内容之一。想要使用该值的其余代码只是进入.then() 处理程序或从那里调用的函数中。一开始你会觉得这很奇怪,但你很快就会习惯的。
【解决方案2】:

这里发生了什么

首先解释一下这里发生了什么。当你做这样的事情时:

var info = new Promise((resolve, reject) => {
  // ...
}).then(result => {
  // ...
}).catch(err => {
  // ...
});

那么info 变量的值最终是一个承诺。那是因为你从new Promise()构造函数返回的promise开始,你调用它的.then()方法返回第二个promise,然后在第二个promise上你调用.catch()方法返回第三个promise——这第三个promise是保存到info 变量中的内容。

所有这些方法调用都会在原始 HTTP 请求完成之前立即返回,因此当您到达下一行时:

console.log(info);

不可能访问来自request() 调用的响应值,因为它还没有发生(此时还没有调用request() 回调)。 info 变量有一个 promise,它是一个对象,您可以使用它来注册您希望在值最终可用时运行的回调。当您将它传递给 console.log() 时,它会打印出这是一个承诺。

如何获取价值

现在,当您想在该值最终可用时打印该值,您可以将一个 Promise 解析回调附加到您拥有的 Promise 中,例如用这样的代码:

info.then((value) => {
  // you can use the value here
  console.log('Value:', value);
}).catch((err) => {
  // the promise got rejected
  console.log('Error:', err);
});

如果您使用的是相对较新的 Node (7.0+) 版本,那么如果您位于使用 async 关键字声明的函数内部,则可以使用 await 来获取 Promise 的分辨率值,如下所示:

(async function () {

  let value = await info;
  console.log(value);

})();

或更短:

(async () => {

  console.log(await info);

})();

(如果您已经在 async 函数中,则不需要 (async () => { ... })(); 包装器。)

工作原理

await 关键字的作用是它从一个隐式生成器函数产生承诺,该函数将控制权传递给外部协程控制代码,该代码将解析和拒绝处理程序附加到产生的承诺并通过返回来自 await 运算符的解析值,或者如果 promise 被拒绝则引发异常。然后生成器可以继续使用返回值并捕获异常,或者它可以让异常冒泡到外部块,在那里它可以被捕获或转换为拒绝 async 函数返回的隐式承诺,如果不一起处理路。

如何使用它

这可能看起来很复杂,但从您的代码的角度来看,它可以让您执行以下操作:

let value = await fun();

(其中fun() 是一个返回promise 的函数)并在value 变量中提供promise 的解析值(实际值,而不是promise)。

请记住,当相关的承诺被拒绝时,await 关键字会引发异常。要处理这种情况,您可以使用 try/catch 块:

try {
  let value = await fun();
  // promise got resolved, you have value here:
  console.log('Value:', value);
} catch (error) {
  // promise got rejected, you have error here:
  console.log('Error:', error);
}

相当于没有新语法的这段代码:

fun().then((value) => {
  // promise got resolved, you have value here:
  console.log('Value:', value);
}).catch((error) => {
  // promise got rejected, you have error here:
  console.log('Error:', error);
});

主要区别在于当您 await 在单个 try 块中处理多个承诺时,变量范围与使用多个链接的 .then() 处理程序不同,每个处理程序都返回一个新的承诺。

您的代码看起来使用了await,但实际上没有

我添加了如何使用await 修复代码的示例,因为您编写代码的方式如下:

var info = new Promise(...);
// here the 'info' variable is set to a promise

真的是这样的:

var info = await new Promise(...);
// here the 'info' variable is set to the value
// that the promise eventually resolves to

更多信息

有关详细信息,请参阅:

节点支持

有关 Node 版本中对该语法的支持,请参阅:

在你没有原生支持 asyncawait 的地方你可以使用 Babel:

或者在语法稍有不同的情况下使用基于生成器的方法,例如 co 或 Bluebird 协程:

【讨论】:

  • 这并没有向 OP 教授或解释如何理解他们的原始代码有什么问题,甚至也没有真正解释为什么这会起作用。好的答案将解释什么是错误的,解释需要以不同的方式做些什么以及为什么并展示一个例子。以你的名声,我当然想你会知道的。而且,对于 OP 的信息,没有必要使用 await 来解决他们的问题。这是一种选择,但肯定不是必需的。一个简单的.then() 也可以。
  • 泰坦之战
  • @jfriend00 这些都是非常好的观点。我通过添加更详细的解释改进了我的答案。谢谢你的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-01
  • 1970-01-01
相关资源
最近更新 更多