如何从Promise中提取数据

时间:2016-04-28 09:59:17

标签: javascript promise ecmascript-6 bluebird es6-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。

2 个答案:

答案 0 :(得分:18)

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

如果你可以使用async/await(你应该很棒),那么你可以编写看似同步的代码,但保留一个诺言的异步性(参见@loganfsmyth评论)。

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

总的来说,由于您已经在使用ES6,我假设您也在使用转换器。在这种情况下,你一定要尝试 async / await 。 请务必在决定中重视,因为它们至今尚未成为批准的规范。

答案 1 :(得分:4)

虽然你可以在async函数中从一个等待的Promise中获取一个值(只是因为它暂停了等待结果的函数),但你不能直接从Promise中获取一个值并返回到同一范围内承诺本身。

那是因为“out of”意味着尝试采取未来存在的东西(最终解决的值)并将其置于过去已经发生的上下文(同步变量赋值)中

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

一般来说,如果你发现自己感觉需要这样做,那么你需要重构某些东西是个好兆头。请注意您在这里使用“result => result.data”进行的操作:

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

.. 已经通过将值传递给函数来处理(字面上,映射)值的情况。但是,假设“//脚本的其余部分”执行与此值相关的重要事项,您可能希望继续映射现在更新的值,然后使用另一个函数,然后执行一些副作用-y与值(如在屏幕上显示数据)。

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

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

老实说这样做更好,因为它要求你清楚地声明发生的特定事件序列,明确地从第一次运行中分离出所有应用程序代码的执行。

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

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

你期望在那里发生什么?有两种可能性,它们都很糟糕。

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