如何从 Promise 中提取数据

How to extract data out of a Promise

我承诺 returns 数据,我想将其保存在变量中。由于异步性质,这在 JavaScript 中是不可能的吗?我是否需要使用 onResolve 作为回调?

我能以某种方式使用它吗(例如用 async/await 包装它):

const { foo, bar } = Promise.then(result => result.data, errorHandler);
// rest of script

而不是这个?

Promise.then(result => {
   const { foo, bar } = result.data;
   // rest of script
 }, errorHandler);

注意:使用 Bluebird 库而不是本机实现,我无法从 Promise 更改为 asnyc/await 或 Generators。

不,您无法像您在示例中建议的那样从承诺中同步 获取数据。数据必须在回调函数中使用。或者,在函数式编程风格中,承诺数据可以是 map()ed over.

如果您使用 async/await 没问题(您应该觉得它很棒),那么您可以编写看起来同步但又保留 promise 异步性的代码(请参阅@loganfsmyth 评论)。

const { foo, bar }  = await iAmAPromise.then(result => result.data);

总的来说,由于您已经在使用 ES6,我假设您也在使用转译器。在这种情况下,您绝对应该尝试 async/await。 请务必考虑到今天它们尚未成为批准规范的决定。

虽然您可以从异步函数中等待的 Promise 中获取值(只是因为它会暂停函数以等待结果),但您永远无法直接从 Promise 中获取值并返回到同一个函数中范围作为 Promise 本身。

那是因为 "out of" 意味着尝试获取未来存在的东西(最终解析的值)并将其放入 已经发生的上下文(同步变量赋值)中过去

也就是穿越。即使时间旅行是可能的,它也可能不是一个好的编码实践,因为时间旅行可能会非常混乱。:)

一般来说,如果您觉得自己需要这样做,这是您需要重构某些内容的好兆头。请注意,您在这里用 "result => result.data" 做什么:

Promise.then(result => result.data, errorHandler);
// rest of script

..是已经您通过将值传递给函数来处理(字面意思是映射)值的情况。但是,假设“// rest of script”做了一些与这个值相关的重要事情,你可能想要 continue 使用另一个函数映射到现在更新的值,然后做一些事情 - effect-y 与值(如在屏幕上显示数据)。

Promise
    .then(result => result.data)
    .then(data => doSomethingWithData)// rest of script
    .catch(errorHandler);

"doSomethingWithData" 将在未来的某个未知时间被调用(if 它曾经被调用过)。这就是为什么将所有这些行为清楚地封装到一个特定的函数中然后将该函数挂接到 Promise 链是一个很好的做法。

老实说,这样更好,因为它要求您明确声明 发生的特定事件序列,明确地与第一个 运行 完全分开您的应用程序代码的执行。

换句话说,想象一下这个场景,假设在全局顶级范围内执行:

const { foo, bar } = Promise.then(result => result.data, errorHandler);
console.log(foo);
//...more program

你希望那里发生什么?有两种可能,而且都是不好的。

  1. 您的整个程序将暂停并等待 Promise 执行 在它知道 "foo" & "bar" 会是什么之前……不, 可能 是什么。 (这是 "await," 在异步函数中实际上做了什么:它暂停 整个函数执行直到值可用或抛出错误)
  2. foo 和 bar 只是未定义的(这实际上是 发生),因为同步执行时,它们只是 顶级 Promise 对象的不存在属性(它本身不是 "value," 而是围绕 获取 最终值或错误的准 Monadic 包装器)这最 可能 甚至还没有包含值。