英文:
JS - Why don't I need return in nested then blocks
问题
我刚刚重构了一些代码,以摆脱一些看起来不太好的嵌套的then
调用。
所以从这个:
axios.get('https://example.com', {})
.then(function (responseOne: any) {
axios.post('https://example.com', {}, {})
.then(function (responseTwo: any) {
axios.put('https://example.com', {}, {})
.then(function (responseThree: any) {
axios.post('https://example.com', {}, {})
.then(function () {
reply.send
})
})
})
})
到
axios.get('https://example.com', {})
.then(function (responseOne: any) {
return axios.post('https://example.com', {}, {})
}).then(function (responseTwo: any) {
return axios.put('https://example.com', {}, {})
}).then(function (responseThree: any) {
return axios.post('https://example.com', {}, {})
}).then(function () {
reply.send
})
我不理解的部分是为什么我必须在第二种方法中添加return
,但在嵌套方法中不需要。
英文:
I'm making some API calls that need to happen in sequence (one after the other, and the previous must be complete before the next one)
I just refactored some code to get rid of some bad looking nested then calls.
(simplified examples here - any
is just for example, and I do actually use responseOne
, responseTwo
and responseThree
)
So went from this:
axios.get('https://example.com', {})
.then(function (responseOne: any) {
axios.post('https://example.com', {}, {})
.then(function (responseTwo: any) {
axios.put('https://example.com', {}, {})
.then(function (responseThree: any) {
axios.post('https://example.com', {}, {})
.then(function () {
reply.send
})
})
})
})
to
axios.get('https://example.com', {})
.then(function (responseOne: any) {
return axios.post('https://example.com', {}, {})
}).then(function (responseTwo: any) {
return axios.put('https://example.com', {}, {})
}).then(function (responseThree: any) {
return axios.post('https://example.com', {}, {})
}).then(function () {
reply.send
})
The bit I don't understand is why I had to add returns in the second approach, but not the nested.
答案1
得分: 2
你必须在要等待解决的承诺上调用 then
。
在每种情况下,该承诺是 axios.post()
的返回值。
在你的第一个示例中,你直接访问该返回值。
在你的第二个示例中,你必须返回该承诺,以便它将被序列中的下一个 then
接受。如果你不这样做,会发生这种情况:
make_first_promise().then(() => {
make_second_promise();
}).then(() => {
// 在第二个承诺解决之前,前一个 `then` 将解决为 `undefined`
});
英文:
You have to call then
on the promise you want to wait to settle.
In each case, that promise is the return value of axios.post()
.
In your first example, you access that return value directly.
In your second example, you have to return the promise so that it will be adopted by the next then
in sequence. If you didn't do that, this would happen:
make_first_promise().then(() => {
make_second_promise();
}).then(() => {
// The previous `then` resolves with `undefined` **before** the second promise has resolved
});
答案2
得分: 1
因为第二种方法链了对.then()
的调用,所以每个调用都需要返回一个Promise
以保持该链的继续。
在原始代码中,没有进行这种链式操作,每个嵌套操作只是在调用下一个操作之前等待其自己的Promise
完成。对于任何给定的操作来说,下一个操作是否也将成为一个Promise
甚至上一个操作是否为Promise
都不重要。
英文:
Because the second approach chains the calls to .then()
, so each one needs to return a Promise
to keep that chain going.
In the original code no such chaining was taking place, and each nested operation was simply waiting for its own Promise
to finish before invoking the next operation. It didn't matter for any given operation if the next one was also going to be a Promise
or even if the previous one was a Promise
.
答案3
得分: 1
考虑以下三种情况:
-
每个
then
方法调用都返回一个 Promise。如果传递给then
方法的回调函数不返回任何内容,那么then
方法的 Promise 将被实现为undefined
值。如果回调函数包含一些异步操作,那么
then
方法返回的 Promise 不会等待 异步操作完成。回调函数中的代码将被执行,then
方法返回的 Promise 会在其回调执行结束后立即实现为undefined
值。 -
如果回调函数返回一个非 Promise 值,那么
then
方法返回的 Promise 将以该值实现。 -
如果回调函数返回一个 Promise,那么
then
方法的 Promise 将被 解析 为回调函数返回的 Promise。简而言之,这意味着外部的then
方法的 Promise(我们称之为p1
)现在依赖于内部回调函数的 Promise(我们称之为p2
)。如果p2
实现,p1
也会以相同的值实现。如果p2
被拒绝,p1
也会以相同的拒绝值被拒绝。换句话说,
p1
将等待p2
来完成,并且p1
不会在p2
完成之前完成。这通常是当then
方法的回调包含异步操作时我们想要的行为。
在你的情况下,如果你不返回 axios.post(...)
的结果,那么第一种情况适用。在这种情况下,下一个 then
方法调用的回调函数将会被传递 undefined
作为参数。然而,在你的情况下,这并不重要。重要的是 then
方法的 Promise 不会等待内部 Promise(由回调函数返回)完成。这不是你想要的行为。
你想要的是每个 then
方法在其回调函数中的 HTTP 请求完成之前等待,然后再调用下一个 then
方法的回调函数。为了实现这一点,你需要返回 axios.post(...)
的结果,这样你的代码就符合上面提到的第三种情况。
英文:
Consider the following three scenarios:
-
Each
then
method call returns a promise. If the callback function passed to thethen
method returns nothing, the promise of thethen
method is fulfilled with the value ofundefined
.If the callback function contains some asynchronous operation, then the promise returned by the
then
method won't wait for the asynchronous operation to complete. The code inside the callback will get executed and the promise returned by thethen
method will fulfil with theundefined
value as soon as its callback execution ends. -
If the callback function returns a non-promise value, the promise returned by the
then
method fulfils with that value. -
If the callback functions returns a promise, then the promise of the
then
method is resolved to the promise returned by the callback function. In simple words, this means that the outerthen
method promise (let's call itp1
) now depends on the inner callback function promise (let's call itp2
). Ifp2
fulfils,p1
also fulfils with the same value. Ifp2
is rejected,p1
also gets rejected with the same rejection value.In other words,
p1
will wait forp2
to settle andp1
won't settle untilp2
settles. This is generally what we want when the callback of thethen
method contains an asynchronous operation.
In your case, if you don't return the result of axios.post(...)
, then the first scenario applies. In this case, the callback function of the next then
method call will be passed undefined
as a parameter. However, in your case, this is not important. What's important is that the then
method promise won't wait for the inner promise (returned by the callback function) to settle. This is not what you want.
What you want is for each then
method to wait for the HTTP request in its callback function to complete before next then
method's callback is invoked. To achieve this, you need to return the result of axios.post(...)
so that your code falls under the 3rd scenario mentioned above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论