Promise.reject в .then () возвращает неопределенное значение - PullRequest
1 голос
/ 23 апреля 2019

В настоящее время у меня есть класс ES6 с конструктором и двумя методами.Я немного запутался, почему использование Promise.reject(ex) в .then() разрешает неопределенное.Если бы кто-то не возражал объяснить, что я делаю неправильно, я был бы очень признателен.

У меня есть метод с именем getYaml(), который содержит следующее:

_getYaml(recordId) {
  return new Promise((resolve, reject) => {
    fs.readFile(this.workingDir + '/' + recordId + '.yaml', 'utf8', function(err, data) {
      if (err) reject(err)
      resolve(data)
    })
  })
}

У меня тогда естьдругой метод с именем getCompDoc, который использует другой метод следующим образом:

getCompDoc(recordId) {
  return this._getYaml(recordId).then(data => {

    let yaml = data

    let yamlObj
    try {
      yamlObj = YAML.safeLoad(yaml)
    } catch (ex) {
      ex.message = `Failure to parse yaml. Error: ${ex.message}`
      logger.error(ex.message, {}, ex)
      return Promise.reject(ex)
    }

    let compDoc = {
      // ...
    }

    return compDoc

  }).catch(err => {
    logger.error(err, {}, err)
  })
}

Затем у меня есть тест, чтобы проверить, обнаружена ли ошибка синтаксического анализа YAML, а затем отклонено обещание, которое выглядит так:

describe('error cases', () => {
  const fakeRecordId = 'SomeYaml'
  beforeEach(() => {
    sinon.stub(myClass, '_getYaml').returns(Promise.resolve('{{&^%}egrinv&alidgj%^%^&$£@£@£}'))
  })

  afterEach(() => {
    myClass._getYaml.restore()
  })

  it('Error parsing yaml, rejects with error', () => {
    return expect(myClass.getCompDoc(fakeRecordId)).to.be.rejected.then(response => {
      expect(response.message).to.match(/Failure to parse yaml. Error: /)
    })
  })
})

Тестовый вывод:

AssertionError: expected promise to be rejected but it was fulfilled with undefined

Если я просто возвращаю исключение, которое выдается в методе getCompDoc, я получаю ошибку, как и ожидалось, однако, как только я использую Promise.reject разрешается с неопределенным.

Я думал об упаковке getCompDoc в return new Promise(), однако я не был уверен, будет ли это примером анти-паттерна конструктора Promise.В идеале я хотел бы отклонить это, вместо того, чтобы возвращать ошибку напрямую, так как тогда я могу утверждать, что метод был отклонен и не выполнен.

1 Ответ

2 голосов
/ 23 апреля 2019

Вы 'глотаете' ошибку в getCompDoc в вашем предложении catch.В частности, вот упрощенный фрагмент, представляющий ваш код:

let getYamlPromise = Promise.reject('REJECTED!');

let getCompDocPromise = getYamlPromise
    .then(data => console.log('getYamlPromise', data))
    .catch(error => console.error('getYamlPromise', error));

getCompDocPromise
    .then(a => console.log('getCompDocPromise RESOLVED', a))
    .catch(a => console.log('getCompDocPromise REJECTED', a));

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

let getYamlPromise = Promise.reject('REJECTED!');

let getCompDocPromise = getYamlPromise
    .then(data => console.log('getYamlPromise', data))
    .catch(error => {
      console.error('getYamlPromise', error);
      return Promise.reject(error);
    });

getCompDocPromise
    .then(a => console.log('getCompDocPromise RESOLVED', a))
    .catch(a => console.log('getCompDocPromise REJECTED', a));
...