Javascript 如何从 Promise 中提取数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36911241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to extract data out of a Promise
提问by Tobias Mühl
I have a promise that returns data and I want to save that in variables. Is this impossible in JavaScript because of the async nature and do I need to use onResolve
as a callback?
我有一个返回数据的承诺,我想将其保存在变量中。由于异步性质,这在 JavaScript 中是不可能的,我是否需要onResolve
用作回调?
Can I somehow use this (e.g. wrap it with async/await):
我可以以某种方式使用它吗(例如用 async/await 包装它):
const { foo, bar } = Promise.then(result => result.data, errorHandler);
// rest of script
instead of this?
而不是这个?
Promise.then(result => {
const { foo, bar } = result.data;
// rest of script
}, errorHandler);
Note: Bluebird library is used instead of native implementation, and I can't change from Promise to asnyc/await or Generators.
注意:使用 Bluebird 库而不是原生实现,我无法从 Promise 更改为 asnyc/await 或 Generators。
回答by silkAdmin
NO you can't get the data synchronouslyout of a promise like you suggest in your example. The data must be used within a callback function. Alternatively in functional programming style the promise data could be map()ed over.
不,您无法像您在示例中建议的那样从承诺中同步获取数据。数据必须在回调函数中使用。或者,在函数式编程风格中,promise 数据可以被map()ed over。
If your are OK using async/await(you should it's awesome) then you can write code that looks synchronous yet retain the asynchronicity of a promise (see @loganfsmyth comments).
如果您可以使用async/await(您应该很棒),那么您可以编写看起来同步但保留承诺的异步性的代码(请参阅@loganfsmyth 评论)。
const { foo, bar } = await iAmAPromise.then(result => result.data);
Overall since you are already using ES6 I assume you are also using a transpiler. In which case you should definitely give async/awaita try. Just be sure to weight in the decision that as today they are not yet a ratified specification.
总的来说,由于您已经在使用 ES6,我假设您也在使用转译器。在这种情况下,您绝对应该尝试async/await。只是一定要在决定中权衡,因为今天它们还没有被批准的规范。
回答by Dtipson
While you can get a value from an awaited Promise inside an async function (simply because it pauses the function to await a result), you can't ever get a value directly out of a Promise and back into the same scope as the Promise itself.
虽然您可以从异步函数中等待的 Promise 中获取值(仅仅是因为它会暂停函数以等待结果),但您永远无法直接从 Promise 中获取值并返回与 Promise 本身相同的作用域.
That's because "out of" would mean trying to take something that exists in the future (the eventually resolved value) and putting it into a context (synchronous variable assignment) that already happened in the past.
那是因为“out of”意味着尝试获取将来存在的某些东西(最终解析的值)并将其放入过去已经发生的上下文(同步变量赋值)中。
That is, time-travel. And even if time-travel were possible, it probably wouldn't be a good coding practice because time travel can be very confusing.:)
也就是时间旅行。即使时间旅行是可能的,它也可能不是一个好的编码实践,因为时间旅行可能会非常混乱。:)
In general, if you find yourself feeling like you need to do this, it's good sign that you need to refactor something. Note that what you're doing with "result => result.data" here:
一般来说,如果您发现自己需要这样做,那么这是您需要重构某些东西的好兆头。请注意,您在此处使用“result => result.data”进行的操作:
Promise.then(result => result.data, errorHandler);
// rest of script
..is alreadya case of you working with (literally, mapping over) the value by passing it to a function. But, assuming that "// rest of script" does something important related to this value, you probably want to continuemapping over the now updated value with yet another function that then does something side-effect-y with the value (like display the data on the screen).
..已经是您通过将值传递给函数来处理(字面意思,映射)该值的情况。但是,假设“// 脚本的其余部分”做了一些与这个值相关的重要事情,你可能想继续用另一个函数映射现在更新的值,然后用这个值做一些副作用(比如显示屏幕上的数据)。
Promise
.then(result => result.data)
.then(data => doSomethingWithData)// rest of script
.catch(errorHandler);
"doSomethingWithData" will be called (ifit's ever called) at some unknown point in the future. Which is why it's a good practice to clearly encapsulate all that behavior into a specific function and then hook that function up to the Promise chain.
“doSomethingWithData”将在未来的某个未知时间点被调用(如果它曾经被调用过)。这就是为什么将所有这些行为清楚地封装到一个特定的函数中,然后将该函数挂接到 Promise 链上是一个很好的做法。
It's honestly better this way, because it requires you to clearly declare a particular sequence of events that willhappen, explicitly separated out from the first run through all of your application code's execution.
老实说,这种方式更好,因为它要求您明确声明将发生的特定事件序列,明确地与所有应用程序代码执行的第一次运行分开。
To put it another way, imagine this scenario, hypothetically executed in the global, top-level scope:
换句话说,想象一下这个场景,假设在全局顶级范围内执行:
const { foo, bar } = Promise.then(result => result.data, errorHandler);
console.log(foo);
//...more program
What would you expect to happen there? There are two possibilities, and both of them are bad.
你希望在那里发生什么?有两种可能,都不好。
- Your entire program would haveto halt and wait for the Promise to execute before it could know what "foo" & "bar" would... nay, mightbe. (this is what "await," inside an async function, does in fact do: it pauses the entire function execution until the value is available or an the error is thrown)
- foo and bar would just be undefined (this is what actually happens), since, as executed synchronously, they'd just be non-existent properties of the top-level Promise object (which is not itself a "value," but rather a quasi-Monadic wrapper around gettingan eventual value OR an error) which most likely doesn'teven contain a value yet.
- 您的整个程序必须暂停并等待 Promise 执行,然后才能知道“foo”和“bar”会是什么……不,可能是。(这是异步函数中的“await”实际上所做的:它暂停整个函数执行,直到值可用或抛出错误)
- foo 和 bar 只是未定义(这就是实际发生的情况),因为在同步执行时,它们只是顶级 Promise 对象的不存在属性(它本身不是“值”,而是一个获取最终值或错误的准 Monadic 包装器),它很可能甚至不包含值。