Разница между ошибкой возврата и ошибкой броска - PullRequest
0 голосов
/ 06 июля 2019

Я нашел следующий код в проекте, который я не понимаю .:

get(key, store = null) {
    if (!key) {
      return new Error('There is no key to get!');
    }

    let dbstore = this.localforage;

    if (store !== null) {
      dbstore = store;
    }

    return dbstore
      .getItem(key)
      .then(function(value) {
        return value;
      })
      .catch(function(err) {
        return new Error('The key (' + key + ") isn't accessible: " + err);
      });
  }

Почему return new Error('There is no key to get!'); вместо throw new Error('There is no key to get!');?

Кроме того, почему бы не выдать ошибку в блоке catch?

1 Ответ

2 голосов
/ 07 июля 2019

Когда вы разрабатываете интерфейс функции и возникают ошибки, у вас есть выбор дизайна, как возвращать ошибки.Если функция синхронная, вы можете либо вернуть какое-нибудь значение часового, которое указывает на ошибку и легко отличить от фактического результата (часто null в Javascript), либо вы можете throw исключение, либо вы можете вернуть объект, который имеетсвойство, которое указывает на успех или неудачу операции.

Если у вас есть асинхронная операция с интерфейсом обещания, обычно отклоняют Promise с объектом Error в качестве причины отклонения, чтобы обозначить ошибку,Это основная теория дизайна обещаний.Успешность разрешается с помощью необязательного значения, ошибки отклоняются с указанием причины.

Этот блок кода:

return dbstore
  .getItem(key)
  .then(function(value) {
    return value;
  })
  .catch(function(err) {
    return new Error('The key (' + key + ") isn't accessible: " + err);
  });

разрешает возвращенное обещание с использованием значения или объекта Error.Как правило, это не то, как пишется код обещания, потому что он требует, чтобы вызывающая сторона проверила тип разрешенного значения, чтобы выяснить, есть ли ошибка или нет, что не является простым, простым способом использования обещаний.Итак, на ваш вопрос, вы обычно делаете это:

return dbstore.getItem(key).catch(function(err) {
    throw new Error('The key (' + key + ") isn't accessible: " + err);
});

Есть и другие признаки в этой функции, что это просто плохой код.

  1. .then(function(value) {return value;})совершенно лишнее и ненужное.Это не добавляет никакой ценности вообще.value уже является разрешенным значением обещания.Не нужно объявлять это снова.

  2. Функция иногда возвращает обещание, а иногда выдает синхронное исключение.
    Это еще более трудная задача для использования.Если вы посмотрите на первый оператор if (!key) {, он вернет объект Error, если аргумент key не указан.Это означает, что для использования этой функции вы должны перехватывать синхронные исключения, предоставлять обработчики .then() и .catch() И проверять тип разрешенного обещания, чтобы увидеть, является ли это объектом ошибки.Эта функция - кошмар для использования.Это плохой код.

Чтобы использовать функцию как есть, вызывающей стороне, вероятно, придется сделать следующее:

let retVal = someObj.get(aKey);
if (typeof retVal === Error) {
    // got some synchronous error
} else {
    retVal.then(val => {
        if (typeof val === Error) {
            // got some asynchronous error
        } else {
            // got an actual successful value here
        }
    }).catch(err => {
        // got some asynchronous error
    })
}

Реализация функции, вероятно, должна быть такой:

get(key, store = null) {
    if (!key) {
        return Promise.reject(new Error('There is no key to get!'));
    }

    let dbstore = store || this.localforage;

    return dbstore.getItem(key).catch(function(err) {
        throw new Error('The key (' + key + ") isn't accessible: " + err);
    });
}

Это можно затем использовать следующим образом:

someObj.get(aKey).then(val => {
    // got some successful value here
}).catch(err => {
    // got some error here
});

Сравните простоту вызывающего абонента с беспорядком выше.

Эта реализация имеет следующие согласованности:

  1. Он всегда возвращает обещание.Если key не предоставлено, возвращается отклоненное обещание.
  2. Все ошибки возникают из-за отклоненного обещания
  3. Значение, с которым разрешается обещание, всегда является действительным успешным значением
  4. Нет обработчика .then(), который не делает ничего полезного.
...