Как правильно обрабатывать ошибки в обещании? - PullRequest
0 голосов
/ 07 февраля 2020

Я видел несколько различных шаблонов для обработки ошибок.

Один похож на:

let result;

try {
    result = await forSomeResult(param);
} catch {
    throw new Error();
}

А другой похож на:

const result = await forSomeResult(param).catch(() => throw new Error());

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

Мне было интересно, есть ли у кого-то техническая ответьте, почему один метод лучше другого.

Ответы [ 2 ]

2 голосов
/ 07 февраля 2020

Прежде всего, нет никаких оснований для catch и throw или .catch() и throw, если вы не собираетесь делать что-то еще в обработчике перехвата или выдавать другую ошибку. Если вы просто хотите, чтобы была выдана та же ошибка, и больше ничего не делаете, то вы можете просто пропустить catch или .catch() и позволить исходному обещанию отклонить go обратно вызывающей стороне.

Тогда , как правило, не рекомендуется смешивать await с .catch(), поскольку за кодом не так просто следовать. Если вы хотите поймать исключение из await, используйте try/catch вокруг него. .catch() работает, это просто не предпочтительный стиль, если вы уже await обещаете.

Техническое различие * между этими двумя стилями:

async function someFunc()
     let x = await fn().catch(err => {
         console.log(err); 
         throw err;
     });
     // do something else with x
     return something;
}

И это:

async function someFunc()
     let x;
     try {
         x = await fn();
     } catch(err) {
         console.log(err);
         throw err;
     }
     // do something else with x
     return something;
}

, если функция fn() вы вызываете throws синхронно (что не должно быть задумано, но может случайно), тогда опция try/catch также поймает это синхронное исключение, а .catch() - нет. Поскольку она находится в функции async, функция async будет перехватывать синхронное исключение и автоматически превращать его в отклоненное обещание для вызывающего абонента, чтобы оно воспринималось как отклоненное обещание, но оно не будет зарегистрировано или обработано в вашем .catch() handler.


Один из наиболее выгодных случаев для try/catch с await - это когда у вас есть несколько операторов await, и вам не нужно обрабатывать ошибки на любом из них в отдельности. Затем вы можете окружить их одним try/catch и перехватить все ошибки в одном месте.

async function someFunc(someFile) {
    let fileHandle;
    try {
        // three await statements in a row, all using same try/catch
        fileHandle = await fsp.open(someFile);
        let data = await fsp.read(...);
        // modify data
        await fsp.write(...)
    } catch(err) {
        // just log and re-throw
        console.log(err);
        throw err;
    } finally {
        // close file handle
        if (fileHandle) {
             await fileHandle.close();
        }
    }
}
0 голосов
/ 07 февраля 2020

Это зависит .

Вы собираетесь вызывать несколько асинхронных функций, которые могут вызвать ошибку? Вы можете обернуть их все в попытку / поймать и выполнять обычную обработку ошибок, не повторяя себя:

try {
    result = await forSomeResult(param);
    await forSomeOtherResult();
    return await finalResult(result);
} catch { //catches all three at once!
    throw new Error();
}

Вам нужно только обрабатывать ошибки для этого, указав c call? Шаблон .catch () в порядке. Не нужно беспокоиться о состоянии гонки: await ожидает обещания разрешить или отклонение, и это включает в себя все обратные вызовы с ошибками и , связанные с обещанием. Тем не менее, в вашем примере вы ловите ошибку только для того, чтобы выбросить пустую - в этом случае может быть предпочтительнее просто написать это:

const result = await forSomeResult(param);

... и позволить ошибке распространиться на вызывающий, естественно.

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

...