英文:
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
thenmethod call returns a promise. If the callback function passed to thethenmethod returns nothing, the promise of thethenmethod is fulfilled with the value ofundefined.If the callback function contains some asynchronous operation, then the promise returned by the
thenmethod won't wait for the asynchronous operation to complete. The code inside the callback will get executed and the promise returned by thethenmethod will fulfil with theundefinedvalue as soon as its callback execution ends. -
If the callback function returns a non-promise value, the promise returned by the
thenmethod fulfils with that value. -
If the callback functions returns a promise, then the promise of the
thenmethod is resolved to the promise returned by the callback function. In simple words, this means that the outerthenmethod promise (let's call itp1) now depends on the inner callback function promise (let's call itp2). Ifp2fulfils,p1also fulfils with the same value. Ifp2is rejected,p1also gets rejected with the same rejection value.In other words,
p1will wait forp2to settle andp1won't settle untilp2settles. This is generally what we want when the callback of thethenmethod 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论