Предотвращение предупреждения «Uncaught (in обещание)».Как избежать блока «ловить»?ES6 обещания против обещаний Q - PullRequest
0 голосов
/ 27 ноября 2018

Мой вопрос состоит из двух частей:

Часть 1

Согласно стандарту ES6 Promise Я вижу, что я вынужден везде использовать блок catch, но он выглядит как copy /вставить и выглядит странно.

Пример:

У меня есть некоторый класс, который делает запрос к бэкэнду (давайте назовем его API class).

И у меня есть несколько требований к классу API с использованием:

1) Мне нужно делать запросы в разных частях моего приложения с обработкой ошибок одного запроса:

// somewhere...
api.getUser().then(... some logic ...);

// somewhere in another module and in another part of app...
api.getUser().then(... some another logic...); 

2) Я хочу, чтобы блоки 'then' работали ТОЛЬКО при успешном выполнении getUsers.

3) Не знаюЯ не хочу писать catch блок везде, где я использую api.getUsers()

api.getUser()
// I don't want following
.catch(e => {
    showAlert('request failed');
})

Поэтому я пытаюсь реализовать обработку одной ошибки внутри класса для всех "запросов пользователей"

class API {
    getUser() {
        let promise = makeRequestToGetUser();
        promise.catch(e => {
            showAlert('request failed');
        });
        return promise;
    }
}

... но если запрос не удался, я все равно вынужден использовать catch block

api.getUser()
    .then(... some logic...)
    .catch(() => {}) // <- I forced to write it to avoid of “Uncaught (in promise)” warning

... в противном случае я получу предупреждение «Uncaught (in обещание)» в консоли.Так что я не знаю, как избежать блока .catch везде, где я использую api экземпляр.

Кажется, это происходит из-за ошибки в таком коде:

// This cause "Uncaught error"
Promise.reject('some value').then(() => {});

Может быть, вы скажете: «просто вернитесь в обещание, которое вы получили в классе».

class API {
    getUser() {
        return makeRequestToGetUser().catch(e => {
            showAlert('request failed');
            return ... 
        });
    }
}

... но это противоречит моему # 2 требованию.

См. эту демонстрацию: https://stackblitz.com/edit/js-xqwiq1?file=index.js

Итак, мой первый вопрос как реализовать описанныйлогика без записи catch блок везде, где я использую api вызов?

часть 2

Я проверил, получит ли та же реализация класса API с библиотекой Qтот же результат и был удивлен , потому что я не получаю “Uncaught (in promise)” warning.Кстати, это более ожидаемое поведение, чем поведение нативных обещаний ES6.

См. Эту демонстрацию https://stackblitz.com/edit/js-g6efg5

На этой странице https://promisesaplus.com/implementations Я обнаружил, что библиотека Q является реализациейОбещания / A + спец.Но почему у него другое поведение?Соответствует ли обещание es6 требованиям Promises / A +?

Кто-нибудь может объяснить, почему эти библиотеки имеют различное поведение, какое из них правильное, и как реализовать упомянутую логику в случае, если «реализация ES6 Promises» верна?

1 Ответ

0 голосов
/ 27 ноября 2018

Я вижу, что я вынужден везде использовать блок catch

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

Если для вас все еще слишком много catch s, вы можете перехватить событие unhandledrejection и предотвратить егопо умолчанию:

window.addEventListener('unhandledrejection', event => {
    event.preventDefault();
    // You can use `event.reason` here for the rejection reason, and
    // `event.promise` for the promise that was rejected
    console.log(`Suppressed the rejection '${event.reason.message}'`);
});

Promise.reject(new Error("Something went wrong"));

Браузер вызовет это событие до того, как сообщит о необработанном отклонении в консоли.

Node.js также поддерживает это на processobject:

process.on('unhandledRejection', error => {
  // `error` is the rejection reason
});

Обратите внимание, что вы получаете причину напрямую, а не как свойство объекта события.

Так что я не знаю, как избежать.catch блокировать везде, где я использую api экземпляр.

Конечно, вызывающий getUser должен знать, что это не удалось?Я имею в виду, если ответ на этот вопрос действительно «нет, они не делают», тогда событие - это путь, но на самом деле код, использующий api, должен выглядеть так:

function useTheAPI() {
    return getUser()
        .then(user => {
            // Do something with user
        });
}

(или async эквивалент), чтобы код, вызывающий useTheAPI, знал, что произошла ошибка;опять же, только верхний уровень должен фактически обработать ошибку.

Кто-нибудь может объяснить, почему эти библиотеки имеют различное поведение, какая из них правильная, и как реализовать упомянутую логику в случае, если "реализация ES6 Promises"правильно?

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

...