如何从 Promise 中提取数据

新手上路,请多包涵

我有返回数据的承诺,我想将其保存在变量中。由于异步性质,这在 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。

原文由 Tobias Mühl 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.8k
2 个回答

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

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

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

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

原文由 silkAdmin 发布,翻译遵循 CC BY-SA 3.0 许可协议

虽然您可以从异步函数内等待的 Promise 中获取值(仅仅是因为它暂停函数以等待结果),但您永远无法直接从 Promise 中获取值并返回到与创建 Promise 本身的代码。

那是因为“脱离”将意味着尝试将未来存在的东西(最终解析的值)放入 过去已经发生 的上下文(同步变量赋值)中。

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

一般来说,如果您发现自己觉得需要这样做,那么这是您需要重构某些东西的好兆头。请注意,您在此处对“result => result.data”所做的操作:

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

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

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

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

老实说,这种方式更好,因为它要求您明确声明 发生的特定事件序列,明确地与应用程序代码的所有执行过程中的第一次运行分开。

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

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

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

  1. 您的整个程序 必须 暂停并等待 Promise 执行,然后才能知道“foo”和“bar”会是什么……不, 可能 是。 (这就是“等待”在异步函数中的作用:它会暂停整个函数的执行,直到值可用或抛出错误为止)
  2. foo 和 bar 只是未定义的(这是实际发生的情况),因为同步执行时,它们只是顶级 Promise 对象的不存在属性(它本身不是一个“值”,而是一个围绕 获取 最终值或错误的准 Monadic 包装器)很可能甚至 还不 包含值。

原文由 Dtipson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题