[javascript] NodeJS UnhandledPromiseRejectionWarning

그래서 이벤트 이미 터를 사용하는 구성 요소를 테스트하고 있습니다. 그렇게하기 위해 Mocha + Chai와 함께 Promises를 사용하는 솔루션을 생각해 냈습니다.

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
    done();
  }).catch((error) => {
    assert.isNotOk(error,'Promise error');
    done();
  });
});

콘솔에 ‘AssertionError : Promise error’메시지가 즉시 표시되므로 거부 함수가 호출되었지만 ‘UnhandledPromiseRejectionWarning’이 나타납니다.

(node ​​: 25754) UnhandledPromiseRejectionWarning : 처리되지 않은 약속 거부 (거부 ID : 2) : AssertionError : 약속 오류 : 예상 {개체 (메시지, showDiff, …)}가 거짓 1 임) 올바른 이벤트로 전환해야 함

그리고 2 초 후

오류 : 시간 초과 2000ms를 초과했습니다. 이 테스트에서 done () 콜백이 호출되고 있는지 확인하십시오.

catch 콜백이 실행 된 이후로 더 이상합니다 (어떤 이유로 든 어설 션 실패로 인해 나머지 실행이 차단되었다고 생각합니다)

이제 재미있는 것은 assert.isNotOk(error...)콘솔에서 경고없이 테스트가 정상적으로 실행 된다는 것 입니다. 캐치를 실행한다는 의미에서 여전히 ‘실패’합니다.
그러나 여전히, 나는 이러한 오류를 약속으로 이해할 수 없습니다. 누군가 나를 밝게 할 수 있습니까?



답변

이 문제는 다음으로 인해 발생합니다.

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

어설 션이 실패하면 오류가 발생합니다. 이 오류는 done()코드가 오류를 일으켰 기 때문에 호출되지 않습니다. 이것이 시간 초과를 일으키는 원인입니다.

“처리되지 않은 약속 거부”가 아니라 오류가 던져 경우 때문에 실패 주장에 의해 발생 catch()핸들러 및 후속가없는 catch()핸들러 (에 설명 된대로 오류가 삼킨 얻을 것이다 이 문서 ). UnhandledPromiseRejectionWarning이 사실을 경고 하는 경고입니다.

일반적으로 Mocha에서 약속 기반 코드를 테스트하려면 Mocha 자체가 이미 약속을 처리 할 수 ​​있다는 사실에 의존해야합니다. 을 사용하지 done()말고 대신 테스트에서 약속을 반환하십시오. 그런 다음 Mocha는 오류 자체를 포착합니다.

이처럼 :

it('should transition with the correct event', () => {
  ...
  return new Promise((resolve, reject) => {
    ...
  }).then((state) => {
    assert(state.action === 'DONE', 'should change state');
  })
  .catch((error) => {
    assert.isNotOk(error,'Promise error');
  });
});


답변

sinon으로 스터 빙 할 때이 오류가 발생했습니다.

해결책은 스텁으로 약속을 해결하거나 거부 할 때 약속대로 npm 패키지를 사용 하는 것입니다.

대신에 …

sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))

사용하다 …

require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));

resolves 메소드도 있습니다 (끝에 s를보십시오).

http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections를 참조 하십시오


답변

Mocha의 어설 션 라이브러리는 어설 션이 올바르지 않은 경우 오류를 발생시켜 작동합니다. 오류를 발생 시키면 catch메소드에 제공된 실행기 함수에서 발생하더라도 약속이 거부됩니다 .

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

위의 코드에서 error객체는 평가되어 true어설 션 라이브러리에서 오류가 발생하지 않습니다. 오류의 결과로 done메소드가 호출되지 않습니다. Mocha의 done콜백은 이러한 오류를 허용하므로 Mocha의 모든 약속 체인을 간단히 종료 할 수 있습니다 .then(done,done). 이를 통해 done 메소드가 항상 호출되고 Mocha가 동기 코드에서 어설 션의 오류를 잡을 때와 같은 방식으로 오류가보고됩니다.

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then(((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
  })).then(done,done);
});

Mocha에서 약속을 테스트 할 때 .then (done, done)을 사용한다는 아이디어에 대해이 기사 를 신뢰합니다 .


답변

UnhandledPromiseRejectionWarning테스트 환경 외부 에서 오류 / 경고를 찾는 사람들에게는 아마도 코드의 아무도 아무도 약속의 최종 오류를 처리하지 않기 때문일 수 있습니다.

예를 들어,이 코드는이 질문에보고 된 경고를 표시합니다.

new Promise((resolve, reject) => {
  return reject('Error reason!');
});

(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!

.catch()오류를 추가 하거나 처리하면 경고 / 오류가 해결됩니다.

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });

또는 then함수 에서 두 번째 매개 변수 사용

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });


답변

나는이 문제에 직면했다 :

(node ​​: 1131004) UnhandledPromiseRejectionWarning : 처리되지 않은 약속 거부 (판정 ID : 1) : TypeError : res.json은 함수가 아닙니다 (노드 : 1131004) DeprecationWarning : 처리되지 않은 약속 거부는 더 이상 사용되지 않습니다. 앞으로 처리되지 않은 약속 거부는 0이 아닌 종료 코드로 Node.j 프로세스를 종료합니다.

실수였습니다. res에서 객체를 바꾸고 then(function(res)있었으므로 res결과로 변경 되어 이제는 작동 중입니다.

잘못된

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(res){//issue was here, res overwrite
                    return res.json(res);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

보정

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(result){//res replaced with result
                    return res.json(result);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

서비스 코드 :

function update(data){
   var id = new require('mongodb').ObjectID(data._id);
        userData = {
                    name:data.name,
                    email:data.email,
                    phone: data.phone
                };
 return collection.findAndModify(
          {_id:id}, // query
          [['_id','asc']],  // sort order
          {$set: userData}, // replacement
          { "new": true }
          ).then(function(doc) {
                if(!doc)
                    throw new Error('Record not updated.');
                return doc.value;
          });
    }

module.exports = {
        update:update
}


답변

E7 async / await에 대한 나의 경험은 다음과 같습니다 .

async helperFunction()테스트에서 전화를 한 경우 … (ES7 async키워드에 대한 설명이 하나 있습니다.)

→ 확인하십시오. await helperFunction(whateverParams) (알다시피 자연스럽게, 일단 알면 …)

그리고 그것이 작동하려면 ( ‘기다리는 예약어’를 피하기 위해) 테스트 함수에 외부 비동기 마커가 있어야합니다.

it('my test', async () => { ...


답변

Chai-Webdriver for Selenium과 비슷한 경험을했습니다. await어설 션에 추가 하고 문제를 해결했습니다.

Cucumberjs를 사용한 예 :

Then(/I see heading with the text of Tasks/, async function() {
    await chai.expect('h1').dom.to.contain.text('Tasks');
});