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


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

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 обратный вызов тогда?

4 54

4 ответа:

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

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

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

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

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

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

для вашего конкретного примера, вы правы в том, что p1 и p2 неотличимы от внешнего мира.

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

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

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

очень интересное наблюдение заключается в том, что если вы используете 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);
})

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

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

кроме того, блок 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);
})

похоже, что лучше всего использовать throw, Если вы не можете, если вы используете некоторые асинхронные задачи, вам придется передать reject обратный вызов до асинхронной функции. Но есть работа вокруг, то есть для обещания вашей асинхронной функции. Подробнее о https://stackoverflow.com/a/33446005