Конструктор обещаний с ошибкой отклонения против ошибки бросания

В следующем коде:

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

Есть ли разница между использованием reject (in p2) из Promise api и выбросом ошибки (в p1) с помощью throw?

Это точно то же самое?

Если это то же самое, почему нам нужен обратный вызов reject, тогда?

Ответ 1

Есть ли разница между использованием reject (in p2) из Promise api и выбросом ошибки (в p1) с помощью throw?

Да, вы не можете использовать throw асинхронно, а reject - обратный вызов. Например, некоторое время ожидания:

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

Это точно то же самое?

Нет, по крайней мере, если другой код не следует за вашим выражением. throw немедленно завершает функцию распознавателя, а вызов reject продолжает выполнение нормально - после того, как "отмечено" обещание как отклонено.

Кроме того, двигатели могут предоставлять информацию об отладке исключений, если вы throw объекты ошибок.

В вашем конкретном примере вы правы, что p1 и p2 неотличимы от внешних.

Ответ 2

Нет, нет, они полностью идентичны. Единственное отличие и почему нам нужно 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);
    });
});

Ответ 3

Я знаю, что это немного поздно, но я действительно не думаю, что любой из этих ответов полностью отвечает на мои вопросы, когда я нашел это. Вот более полный пример для игры.

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

Очень интересное замечание состоит в том, что если вы используете throw, он будет обрабатываться сначала обработчиком reject, а затем обработчиком error, если обработчик отклонения не находится на месте.

С блоком обработчика отклонения

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