Шаблон первой ошибки для ES7 Async / Await

Исправлять ошибки - это не весело. В этой статье я покажу вам схему работы с ошибками в Async / Await. Этот шаблон избегает использования try / catch.

// Callback
fetch(URL, (error, response) => ...)
// Promise
fetch(URL).then((response) => ...).catch((error) => ...)
// Async / await
try { fetch(URL) } catch (error) {...}

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

Эта проблема

async fetchData() {
    let json;
    try {
        const response = await fetch(URL)
        try {
             json = await response.json()
        } catch (error) {
             console.log("Parsing failed", error)
             return
        }
    } catch (error) {
        console.log("Request failed", error)
        return
    }
    const stars = json.stargazers_count
    this.setState({stars})
}

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

Перейти к заявлению, которое считается вредным - Эдсгер Дейкстра 1968

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

Итак, мы перешли от явного описания возвращаемых ошибок к выбрасыванию исключений, это не похоже на прогресс.

Возможное решение

async fetchData() {
    const [responseError, response] = await fetch(URL);
    if (responseError || !response) {
        console.log("Request failed", responseError)
        return
    }
    const [parseError, json] = await response.json()
    if (parseError || !json) {
        console.log("Request failed", parseError)
        return
    }
    const stars = json.stargazers_count
    this.setState({stars})
}

При этом используется деструктуризация массива, и, поскольку ошибка является первым значением, это заставляет задуматься об обработке ошибок. Я смешал обработку ошибок Go с обратными вызовами при первой ошибке NodeJS.

Детали реализации

const errorFirstPromise = (promise) => {
    return new Promise((resolve) => {
        return promise.then((result) => {
            return resolve([null, result])
        }).catch((error) => {
            return resolve([error, null])
        })
    })
}

Если кто-то думает, что это хороший шаблон, я соберу узел узла. Пожалуйста, оставьте комментарий.

Обновление: я опубликовал модуль npm для этого шаблона: https://www.npmjs.com/package/error-first