JS – 为什么在嵌套的”then”块中不需要使用”return”

huangapple go评论66阅读模式
英文:

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

考虑以下三种情况:

  1. 每个 then 方法调用都返回一个 Promise。如果传递给 then 方法的回调函数不返回任何内容,那么 then 方法的 Promise 将被实现为 undefined 值。

    如果回调函数包含一些异步操作,那么 then 方法返回的 Promise 不会等待 异步操作完成。回调函数中的代码将被执行,then 方法返回的 Promise 会在其回调执行结束后立即实现为 undefined 值。

  2. 如果回调函数返回一个非 Promise 值,那么 then 方法返回的 Promise 将以该值实现。

  3. 如果回调函数返回一个 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:

  1. Each then method call returns a promise. If the callback function passed to the then method returns nothing, the promise of the then method is fulfilled with the value of undefined.

    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 the then method will fulfil with the undefined value as soon as its callback execution ends.

  2. If the callback function returns a non-promise value, the promise returned by the then method fulfils with that value.

  3. 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 outer then method promise (let's call it p1) now depends on the inner callback function promise (let's call it p2). If p2 fulfils, p1 also fulfils with the same value. If p2 is rejected, p1 also gets rejected with the same rejection value.

    In other words, p1 will wait for p2 to settle and p1 won't settle until p2 settles. This is generally what we want when the callback of the then 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.

huangapple
  • 本文由 发表于 2023年3月7日 21:38:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75662702.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定