Javascript 在 Promise 中混淆错误和拒绝

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35282803/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:31:33  来源:igfitidea点击:

Confuse about error and reject in Promise

javascriptpromise

提问by Kuan

All:

全部:

I am pretty new to JS Promise, there is one confuse when it comes to Promise chaining, say I have a promise chaining like:

我对 JS Promise 很陌生,当谈到 Promise 链时,有一个困惑,比如我有一个像这样的承诺链:

var p = new Promise(function(res, rej){
})
.then(
    function(data){
    }, 
    function(err){
    })
.then(
    function(data){
    }, 
    function(err){
    })
.catch(
    function(err){
    })

What confuse me:

什么让我困惑:

  1. When the function(err) get called and when the catch get called?
  2. How to resolve and reject in then?
  1. 何时调用函数(错误)以及何时调用 catch?
  2. 如何解决和拒绝then

Thanks

谢谢

采纳答案by rabbitco

The formular for using a Promise is:

使用 Promise 的公式是:

var p = new Promise(function(resolve, reject) {

  var condition = doSomething();

  if (condition) {
    resolve(data);
  } else {
    reject(err);
  }

});

There is nothing special about .catch, it is just sugar for .then (undefined, func), but .catchmore clearly communicates that it is purely an error handler.

没有什么特别之处.catch,它只是为 加糖.then (undefined, func),但.catch更清楚地表明它纯粹是一个错误处理程序。

If a Promisedoes not resolve and no rejection callback is provided in it, it skips forward to the next .thenin the chain with a rejection callback in it. The rejection callback is the reject(err).

如果 aPromise未解析并且其中没有提供拒绝回调,则它会向前跳到.then链中包含拒绝回调的下一个。拒绝回调是reject(err).

For more detailed explanations see: Javascript Promises - There and Back again.

有关更详细的解释,请参阅:Javascript Promises - There and Back again



That is: in your example the .catchonly gets called if the preceding rejection callback has an error in it. That is there is an error in the reject(err)function itself - which has nothing to do with the preceding Promisenot resolving.

那就是:在您的示例中, . catch只有在前面的拒绝回调中有错误时才会被调用。那是reject(err)函数本身存在错误- 这与前面的Promise未解析无关。

You can essentially limit yourself to a rejection callback in the .catchat you end of the .thenchain. Any Errorin any .thenwill then fall through to the .catch. One subtlety though: any error in the .catchis not caught.

您基本上可以将自己限制.catch.then链末端的拒绝回调中。Any Errorin any.then将落入.catch. 但是有一个微妙之处:.catch没有发现中的任何错误。

回答by Dtipson

The important thing to know is that the .then() method is always chained ontoa Promise, and it returns a newPromise whose value and resolved/rejected state is based on what the function given to it returned.

要知道的重要一点是 .then() 方法总是链接一个 Promise 上,它返回一个新的Promise,其值和已解决/拒绝状态基于给它的函数返回的内容。

In your example, if the original Promise resolves, then the first function in your first .then() will get called with the resolved value. If it returns a value then whatever value itreturns will then get ultimately passed into the first function in your second.then(). The function in catch will never get called.

在您的示例中,如果原始 Promise 已解析,则您的第一个 .then() 中的第一个函数将使用已解析的值进行调用。如果它返回一个值,那么它返回的任何值将最终传递到第二个.then() 中的第一个函数中。catch 中的函数永远不会被调用。

If the Promise rejects, the second function in your first .then() will get called with the rejected value, and whatever valueit returns will become a new resolved Promise which passes into the first function of your second then. Catch is never called here either. It's only if the Promise rejects and you keep returning rejected Promises or throwing errors in both your function(err){}functionsthat you'll get the function(err){}in your catch block called.

如果 Promise 拒绝,则第一个 .then() 中的第二个函数将使用被拒绝的值调用,无论它返回什么,都将成为一个新的已解析 Promise,并传递到第二个 then 的第一个函数中。Catch 也从不在这里调用。只有当 Promise 拒绝并且您不断返回被拒绝function(err){}的 Promise或在您的两个函数抛出错误时,您才会function(err){}在 catch 块中调用 。

To resolve in your function(data){}functions, all you need to do is return a value (or return a Promise/thenable that later resolves). To reject, you would need to either throw an error, actually causean error, return a new Promise that eventually rejects, or explicitly return Promise.reject(::some value::).

要在您的function(data){}函数中解析,您需要做的就是返回一个值(或返回一个稍后解析的 Promise/thenable)。要拒绝,您需要抛出错误、实际导致错误、返回最终拒绝的新 Promise 或显式 return Promise.reject(::some value::)

To resolve in your function(err){}blocks, all you need to do is return a new value. You could also return a Promise, in which case that Promise is what will be returned (eventually resolving or rejecting).

要在function(err){}块中解析,您需要做的就是返回一个新值。您还可以返回一个 Promise,在这种情况下,将返回 Promise(最终解决或拒绝)。

In general, it's not wise to define both the resolved and rejected path in the same .then() though: PROMISE.then(fn).catch(fn)is a much safer/clearer practice, because then any errors in the first .then() will be caught by catch. If you do PROMISE.then(fn, fn)instead though, if an error happens in the first function it would NOT get caught by the second: some later chained on method would have to catch it.

一般来说,在同一个 .then() 中同时定义已解决和被拒绝的路径是不明智的:这PROMISE.then(fn).catch(fn)是一种更安全/更清晰的做法,因为第一个 .then() 中的任何错误都将被 catch 捕获。PROMISE.then(fn, fn)但是,如果你这样做,如果第一个函数中发生错误,它就不会被第二个函数捕获:一些后来链接的方法必须捕获它。

回答by traktor53

  1. Note the example executor function in

    var p = new Promise(function(res, rej){});

    is incomplete. An actual executor function supplied to the Promise constructor must call its first argument (res) to resolve the constructed promise, or its second argument (rej) to reject the promise. These calls are normally made asynchronously but don't have to be in ES6.

  2. When a promise is resolved with a Promise object (or any object with a .thenproperty which is a function) nothing happens until the promise object supplied in resolution itself becomes fulfilledor rejected. Fulfilled values are passed to .thenonFulfilledhandlers, rejected values are passed to .thenonRejectedhandlers/listeners/callbacks (depending on your terminology).

  3. But when a promise is resolved with a non promise (like) object, listeners supplied as the first parameter to .thenare called with the resolution value.

  4. When a promise is rejected with any value, listeners supplied as the second parameter to .then, or first parameter to .catch, are called with the rejected value.

  5. .catchis a euphemism for calling .thenwith the supplied argument as second parameter and omitting the first parameter, as in

    Promise.prototype.catch = function( listener) { return this.then(null, listener);};

  6. The behavior of .thenregistered onFulfilland onRejectfunctions is the same. To reject a chained promise throw an error. To fulfill a chained promise return a non promise value. To hold up a chained promise return a promise (or promise like) object.


  7. (Update) When a parameter supplied to .then( onFulfill, onReject)is missing or not a function object, processing is equivalent to supplying a dummy function from:

    function onFulfill( data) { return data;}
    function onReject( err) { throw err;}
    

    This is the usual case when calling thenor catchwith a single argument.

  1. 请注意中的示例执行程序函数

    var p = new Promise(function(res, rej){});

    不完整。提供给 Promise 构造函数的实际执行器函数必须调用其第一个参数 ( res) 来解析构造的承诺,或者调用其第二个参数 ( rej) 来拒绝该承诺。这些调用通常是异步进行的,但不必在 ES6 中进行。

  2. 当使用 Promise 对象(或具有.then作为函数的属性的任何对象)解析 Promise时,直到解析中提供的 Promise 对象本身变得满足拒绝时,才会发生任何事情。实现的值传递给.thenonFulfilled处理程序,拒绝的值传递给.thenonRejected处理程序/侦听器/回调(取决于您的术语)。

  3. 但是,当使用非承诺(类似)对象解析承诺时,作为第一个参数提供的侦听.then器将使用解析值调用。

  4. 当使用任何值拒绝承诺时,作为第二个参数 to.then或第一个参数 to提供的侦听.catch器将使用被拒绝的值调用。

  5. .catch.then使用提供的参数作为第二个参数进行调用并省略第一个参数的委婉说法,如

    Promise.prototype.catch = function( listener) { return this.then(null, listener);};

  6. .then注册onFulfillonReject函数的行为是相同的。拒绝一个链式承诺会抛出一个错误。履行一个链式承诺返回一个非承诺值。阻止一个链式承诺返回一个承诺(或承诺之类的)对象。


  7. (更新)当提供给的参数.then( onFulfill, onReject)丢失或不是函数对象时,处理等效于从以下位置提供虚拟函数:

    function onFulfill( data) { return data;}
    function onReject( err) { throw err;}
    

    这是调用thencatch使用单个参数时的常见情况。