Я знаю, що це давнє запитання, але я просто наткнувся на нитку, і тут, мабуть, виникає конфлікт між помилками та відхиленням, що стикається (хоча б у багатьох випадках) часто повторюваних порад не використовувати обробку виключень для розглядайте очікувані випадки. Для ілюстрації: якщо метод асинхронізації намагається пройти автентифікацію користувача, а автентифікація не вдалася, це відхилення (один з двох очікуваних випадків), а не помилка (наприклад, якщо API аутентифікації був недоступний.)
Щоб переконатися, що я не просто розщеплював волоски, я провів перевірку працездатності трьох різних підходів до цього, використовуючи цей код:
const iterations = 100000;
function getSwitch() {
return Math.round(Math.random()) === 1;
}
function doSomething(value) {
return 'something done to ' + value.toString();
}
let processWithThrow = function () {
if (getSwitch()) {
throw new Error('foo');
}
};
let processWithReturn = function () {
if (getSwitch()) {
return new Error('bar');
} else {
return {}
}
};
let processWithCustomObject = function () {
if (getSwitch()) {
return {type: 'rejection', message: 'quux'};
} else {
return {type: 'usable response', value: 'fnord'};
}
};
function testTryCatch(limit) {
for (let i = 0; i < limit; i++) {
try {
processWithThrow();
} catch (e) {
const dummyValue = doSomething(e);
}
}
}
function testReturnError(limit) {
for (let i = 0; i < limit; i++) {
const returnValue = processWithReturn();
if (returnValue instanceof Error) {
const dummyValue = doSomething(returnValue);
}
}
}
function testCustomObject(limit) {
for (let i = 0; i < limit; i++) {
const returnValue = processWithCustomObject();
if (returnValue.type === 'rejection') {
const dummyValue = doSomething(returnValue);
}
}
}
let start, end;
start = new Date();
testTryCatch(iterations);
end = new Date();
const interval_1 = end - start;
start = new Date();
testReturnError(iterations);
end = new Date();
const interval_2 = end - start;
start = new Date();
testCustomObject(iterations);
end = new Date();
const interval_3 = end - start;
console.log(`with try/catch: ${interval_1}ms; with returned Error: ${interval_2}ms; with custom object: ${interval_3}ms`);
Деякі речі, які є там, включені через мою невпевненість щодо інтерпретатора Javascript (я люблю опускатись по одній кролячій норі за раз); Наприклад, я включив doSomething
функцію і призначив її повернення, dummyValue
щоб гарантувати, що умовні блоки не будуть оптимізовані.
Мої результати:
with try/catch: 507ms; with returned Error: 260ms; with custom object: 5ms
Я знаю, що існує маса випадків, коли не варто клопотатись про невеликі оптимізації, але в масштабніших системах ці речі можуть призвести до великої сукупності, і це досить неповторне порівняння.
Так ... хоча я вважаю, що підхід прийнятої відповіді звучить у випадках, коли ви очікуєте, що вам доведеться обробляти непередбачувані помилки в рамках функції асинхронізації, у випадках, коли відхилення просто означає, що "вам доведеться йти з планом B (або C, або D ...) "Я думаю, що моїм перевагою було б відхилити використання спеціального об'єкта відповіді.
Promise
конструктора антипатерні ! Навіть перший фрагмент мав бути написанийfoo(id: string): Promise<A> { return someAsyncPromise().then(()=>{ return 200; }, ()=>{ throw 400; }); }