简体   繁体   English

为什么.then()在JavaScript中没有承诺?

[英]Why does .then() work without a promise in JavaScript?

Why does calling the second function .then(notPromise) still pass the argument to the third function .then(promiseC) even though notPromise() is just a regular function? 为什么调用第二个函数.then(notPromise)仍然将参数传递给第三个函数.then(promiseC),即使notPromise()只是一个常规函数?

I thought only promises can be used with .then() but somehow it still executes (and passes the arguments) properly. 我认为只有promises可以与.then()一起使用,但不知何故它仍然可以正确执行(并传递参数)。

 promiseA() .then(notPromise) .then(promiseC); function promiseA() { return new Promise(function (resolve, reject) { const string = "a"; resolve(string); }); } function notPromise(string) { const nextString = "b" const finalString = string + nextString; return finalString; } function promiseC(string) { return new Promise(function (resolve, reject) { const nextString = "c"; const finalString = string + nextString; alert(finalString); resolve(finalString); }); } 

The then() method returns a Promise. then()方法返回一个Promise。 See docs . 查看文档

A promise has a handler method. promise有一个处理程序方法。 Once a Promise is fulfilled or rejected, the respective handler function will be called asynchronously. 一旦Promise被完成或拒绝,将异步调用相应的处理函数。 The behavior of the handler function follows a specific set of rules as stated here . 处理程序函数的行为遵循此处所述的一组特定规则。

Let's go over them one by one. 我们一个接一个地回顾一下。 Here is the code we will inspect side by side. 这是我们将并排检查的代码。 Its nothing special, just a chain of promises returning values. 它没什么特别的,只是一连串的承诺回归价值。

let sequence = new Promise(function (resolve) {
  console.log('Say 1')
  resolve(1)
})

sequence
  .then(() => {
    console.log('Say 2')
    return 2
  })
  .then(() => {
    console.log('Say 3')
  })
  .then(() => {
    console.log('Say 4')
    return Promise.resolve(4)
  })
  .then(() => {
    return new Promise(function (resolve) {
      console.log('Say 5')
      setTimeout(() => { resolve(5) }, 1000)
    })
  })
  1. returns a value, the promise returned by then gets resolved with the returned value as its value; 返回一个值,然后返回的promise将以返回值作为其值来解析;

In code, this is Say 2 , and your original question. 在代码中,这是Say 2 ,以及您的原始问题。 When a value is returned, then() returns a Promise which is resolved with the value your returned. 返回值时, then()返回一个Promise,使用返回的值解析该Promise。

  1. doesn't return anything, the promise returned by then gets resolved with an undefined value; 不返回任何内容,然后返回的promise将以未定义的值解析;

same as above. 与上述相同。

  1. throws an error, the promise returned by then gets rejected with the thrown error as its value; 抛出一个错误,然后返回的promise被抛出错误作为其值被拒绝;

same as above, except now then() returns a Promise which is rejected with your error. 与上面相同,除了now then()返回一个Promise,它会被你的错误拒绝。

  1. returns an already resolved promise, the promise returned by then gets resolved with that promise's value as its value; 返回已经解析的promise,然后返回的promise将以promise的值作为其值来解析;

In code this is Say 4 , where the promise has already been resolved. 在代码中,这是Say 4 ,其中promise已经解决。 So now then() returns a Promise which is resolved with the value 4. 所以现在then()返回一个使用值4解析的Promise。

  1. returns an already rejected promise, the promise returned by then gets rejected with that promise's value as its value; 返回一个已被拒绝的promise,然后返回的promise将被拒绝,并将该promise的值作为其值;

same as above, except it now rejects. 同上,但现在拒绝。

  1. returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. 返回另一个待处理的promise对象,当时返回的promise的解析/拒绝将在处理程序返回的promise的解析/拒绝之后。 Also, the value of the promise returned by then will be the same as the value of the promise returned by the handler. 此外,then返回的promise的值将与处理程序返回的promise的值相同。

In code, this is Say 5 . 在代码中,这是Say 5 If you return a promise which has not been resolved yet, then() will return a Promise with the results of your promise ie 5. 如果您返回尚未解决的承诺, then()将返回一个Promise,其中包含您的承诺的结果,即5。

One thing to note, that I also actually learned recently (suggested by @Bergi in comments) was that the then() method always constructs and returns a new Promise before the chain callbacks have even started to execute. 有一点需要注意的是,我最近实际学习过的(@Bergi在评论中提到)是then()方法总是在链回调甚至开始执行之前构造并返回一个新的Promise。 The callbacks that you pass to then() simply tells the promise the value/error that the promise should resolve/reject with. 传递给then()的回调只是告诉promise承诺应该解析/拒绝的值/错误。

In summary, that is why then() chaining works even when you don't specifically return a new Promise - because then() method always constructs a new promise behind the scenes and rejects/resolves that promise with the value you returned. 总而言之,这就是为什么then()链接即使你没有专门返回一个新的Promise也是如此 - 因为then()方法总是在幕后构造一个新的promise并拒绝/解析你所返回的值的promise。 The most complex case in above scenarios is when you return a Promise in your callback, in which case your callback promise's results are passed to the then() promise. 上述场景中最复杂的情​​况是在回调中返回Promise,在这种情况下,回调promise的结果将传递给then() promise。

It has to do with the promise chain, it doesn't matter if subsequent calls to then() are not promises, they are all part of the promise chain, the good thing is you can continue chaining promises, which allows you to do several async/promise operations in a row (as your example described), here is a real world example: 它与promise链有关,如果对then()后续调用不是promises,它们都是promise链的一部分并不重要,好的是你可以继续链接promises,这可以让你做几个连续执行async / promise操作(如上所述),这是一个真实的例子:

  // This is the generic http call
  private callServer(url: string, method: string, body?: any) {
    const uri = env.apiUrl + url;
    const session = this.sessionToken;

    const headers = {
      'Content-Type': 'application/json',
      'credentials': 'same-origin',
      'x-auth-token': session,
    };

    return fetch(uri, {
      method,
      headers,
      body: JSON.stringify(body),
    })
      .then(this.wait) // this is a timer, returns a promise
      .then(this.checkStatus) // this is a sync call
      .then((r) => r.text()) // r.text() is async
      .then((tx) => tx ? JSON.parse(tx) : {}); // this is sync
  }

You can read more about the promise chain here 您可以在此处阅读有关承诺链的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM