javascript 带有拒绝调用的承诺构造函数与抛出错误

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

Promise constructor with reject call vs throwing error

javascriptpromise

提问by lante

In the following code:

在以下代码中:

var p1 = new Promise(function (resolve, reject) {
    throw 'test1';
});

var p2 = new Promise(function (resolve, reject) {
    reject('test2');
});

p1.catch(function (err) {
    console.log(err); // test1
});

p2.catch(function (err) {
    console.log(err); // test2
});

Is there any difference between using reject(in p2) from the Promiseapi, and throwing an error (in p1) using throw?

从api使用reject(in p2)Promise和使用 抛出错误 (in p1)之间有什么区别throw吗?

Its exactly the same?

它完全一样吗?

If its the same, why we need a rejectcallback then?

如果相同,那为什么我们需要reject回调呢?

回答by Bergi

Is there any difference between using reject(in p2) from the Promiseapi, and throwing an error (in p1) using throw?

从api使用reject(in p2)Promise和使用 抛出错误 (in p1)之间有什么区别throw吗?

Yes, you cannotuse throwasynchronously, while rejectis a callback. For example, some timeout:

是的,您不能throw异步使用,reject而是回调。例如,一些超时:

new Promise(_, reject) {
    setTimeout(reject, 1000);
});

Its exactly the same?

它完全一样吗?

No, at least not when other code follows your statement. throwimmediately completes the resolver function, while calling rejectcontinues execution normally - after having "marked" the promise as rejected.

不,至少当其他代码遵循您的语句时不会。throw立即完成解析器功能,同时调用reject继续正常执行 - 在将承诺“标记”为拒绝后。

Also, engines might provide different exception debugging information if you throwerror objects.

此外,如果您throw错误对象,引擎可能会提供不同的异常调试信息。

For your specific example, you are right that p1and p2are indistinguishable from the outside.

对于您的具体示例,您是对的,p1并且p2与外部无法区分。

回答by Benjamin Gruenbaum

No, there is not, the two are completely identical. The only difference and why we need rejectis when you need to reject asynchronously - for example if you're converting a callback based API it might need to signal an asynchronous error.

不,没有,两者完全相同。唯一的区别以及我们需要的原因reject是当您需要异步拒绝时 - 例如,如果您正在转换基于回调的 API,它可能需要发出异步错误信号。

var p = new Promise(function(resolve, reject){
    someCallbackApi(function(err, data){
        if(err) reject(err); // CAN'T THROW HERE, non promise context, async.
        else resolve(data);
    });
});

回答by Jonathan Rys

I know this is a bit late, but I don't really think either of these answers completely answers the questions I had when I found this, Here is a fuller example to play with.

我知道这有点晚了,但我真的不认为这些答案中的任何一个都完全回答了我发现这个问题时的问题,这是一个更完整的例子。

var p1 = new Promise(function (resolve, reject) {
    throw 'test 1.1'; //This actually happens
    console.log('test 1.1.1'); //This never happens
    reject('test 1.2'); //This never happens because throwing an error already rejected the promise
    console.log('test 1.3'); //This never happens
});

var p2 = new Promise(function (resolve, reject) {
    reject('test 2.1'); //This actually happens
    console.log('test 2.1.1'); //This happens BEFORE the Promise is rejected because reject() is a callback
    throw 'test 2.2'; //This error is caught and ignored by the Promise
    console.log('test 2.3'); //This never happens
});

var p3 = new Promise(function (resolve, reject) {
    setTimeout(function() { reject('test 3.1');}, 1000); //This never happens because throwing an error already rejected the promise
    throw('test 3.2'); //This actually happens
    console.log('test 3.3'); //This never happens
});

var p4 = new Promise(function (resolve, reject) {
    throw('test 4.1'); //This actually happens
    setTimeout(function() { reject('test 4.2');}, 1000); //This never happens because throwing an error already rejected the promise
    console.log('test 4.3'); //This never happens
});

var p5 = new Promise(function (resolve, reject) {
    setTimeout(function() { throw('test 5.1');}, 1000); //This throws an Uncaught Error Exception
    reject('test 5.2'); //This actually happens
    console.log('test 5.3'); //This happens BEFORE the Promise is rejected because reject() is a callback
});

var p6 = new Promise(function (resolve, reject) {
    reject('test 6.1'); //This actually happens
    setTimeout(function() { throw('test 6.2');}, 1000); //This throws an Uncaught Error Exception
    console.log('test 6.3'); //This happens BEFORE the Promise is rejected because reject() is a callback
});


p1.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test1
});

p2.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test2
});

p3.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test3
});

p4.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test4
});

p5.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test5
});

p6.then(function (resolve) {
    console.log(resolve, "resolved")
}, function (reject) {
    console.log(reject, "rejected")
}).catch(function (err) {
    console.log(err, "caught"); // test6
});

回答by Gavin

A very interesting observation is that if you use throwit will be handled by first the rejecthandler & then theerrorhandler if a reject handler is not in place.

一个非常有趣的观察是,如果您使用throw它,它将首先由reject处理程序处理,然后在error没有拒绝处理程序的情况下由处理程序处理。

With reject handler block

使用拒绝处理程序块

var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
  if (allowed)
    resolve('Success');
  else
//         reject('Not allowed');
    throw new Error('I threw an error')
})

p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
}, function(rejected) {
console.log('Inside reject handler, rejected value: ' + rejected);
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})

Without reject handler block

没有拒绝处理程序块

var allowed = false;
var p1 = new Promise(
function(resolve, reject) {
  if (allowed)
    resolve('Success');
  else
//         reject('Not allowed');
    throw new Error('I threw an error')
})

p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})

Additionally, the catch block will be able catch any error thrown inside the resolvehandler.

此外,catch 块将能够捕获resolve处理程序中抛出的任何错误。

var allowed = true;
var p1 = new Promise(
function(resolve, reject) {
  if (allowed)
    resolve('Success');
  else
//         reject('Not allowed');
    throw new Error('I threw an error')
})

p1.then(function(fulfilled) {
console.log('Inside resolve handler, resolved value: ' + fulfilled);
throw new Error('Error created inside resolve handler block');
}).catch(function(error) {
console.log('Inside error handler, error value: ' + error);
})

It looks like it's best to use throw, unless you can't if you are running some async task, you will have to pass the rejectcallback down to the async function. But there's a work around, that is is to promisifying your async function. More on https://stackoverflow.com/a/33446005

看起来最好使用throw,除非您不能运行某些异步任务,否则您必须将reject回调传递给异步函数。但是有一个变通方法,那就是承诺你的异步功能。更多关于https://stackoverflow.com/a/33446005