带有拒绝调用和抛出错误的诺言构造函数

时间:2022-08-23 11:33:21

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 Promise api, and throwing an error (in p1) using throw?

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

Its exactly the same?

一模一样的吗?

If its the same, why we need a reject callback then?

如果它是相同的,那么为什么我们需要一个拒绝回调呢?

4 个解决方案

#1


56  

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

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

Yes, you cannot use throw asynchronously, while reject is a callback. For example, some timeout:

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

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

Its exactly the same?

一模一样的吗?

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

不,至少当其他代码遵循您的语句时不会。抛出立即完成解析器函数,而调用拒绝在正常情况下继续执行——在“标记”了被拒绝的承诺之后。

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

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

For your specific example, you are right that p1 and p2 are indistinguishable from the outside.

对于您的具体示例,您是对的,p1和p2与外部是不可区分的。

#2


30  

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

不,没有,这两个完全相同。唯一的区别和我们需要拒绝的原因是当您需要异步拒绝时—例如,如果您正在转换一个基于回调的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);
    });
});

#3


28  

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
});

#4


0  

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

一个非常有趣的观察是,如果您使用throw,它将首先由拒绝处理程序处理,如果拒绝处理程序不存在,则由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 resolve handler.

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

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 reject callback down to the async function. But there's a work around, that is is to promisifying your async function. More on https://*.com/a/33446005

看起来最好使用throw,除非您在运行异步任务时不能使用,否则必须将拒绝回调传递给async函数。但是有一个工作,那就是推广你的异步函数。在https://*.com/a/33446005上更

#1


56  

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

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

Yes, you cannot use throw asynchronously, while reject is a callback. For example, some timeout:

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

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

Its exactly the same?

一模一样的吗?

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

不,至少当其他代码遵循您的语句时不会。抛出立即完成解析器函数,而调用拒绝在正常情况下继续执行——在“标记”了被拒绝的承诺之后。

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

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

For your specific example, you are right that p1 and p2 are indistinguishable from the outside.

对于您的具体示例,您是对的,p1和p2与外部是不可区分的。

#2


30  

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

不,没有,这两个完全相同。唯一的区别和我们需要拒绝的原因是当您需要异步拒绝时—例如,如果您正在转换一个基于回调的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);
    });
});

#3


28  

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
});

#4


0  

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

一个非常有趣的观察是,如果您使用throw,它将首先由拒绝处理程序处理,如果拒绝处理程序不存在,则由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 resolve handler.

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

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 reject callback down to the async function. But there's a work around, that is is to promisifying your async function. More on https://*.com/a/33446005

看起来最好使用throw,除非您在运行异步任务时不能使用,否则必须将拒绝回调传递给async函数。但是有一个工作,那就是推广你的异步函数。在https://*.com/a/33446005上更