처리되지 않은 약속 거부 란 무엇입니까?


203

Angular 2를 배우기 위해 튜토리얼을 시도하고 있습니다.

다음과 같은 오류가 발생합니다.

(node:4796) UnhandledPromiseRejectionWarning: Unhandled promise rejection (r                                                                                                     ejection id: 1): Error: spawn cmd ENOENT
[1] (node:4796) DeprecationWarning: Unhandled promise rejections are deprecated.
In the future, promise rejections that are not handled will terminate the Node.
js process with a non-zero exit code.

나는 SO에서 다른 질문과 답변을 겪었지만 "처리되지 않은 약속 거부"가 무엇인지 알 수 없었습니다.

누구든지 단순히 그것이 무엇 Error: spawn cmd ENOENT이고 무엇 이고 언제 발생하는지, 그리고이 경고를 제거하기 위해 확인해야 할 것을 설명 할 수 있습니까?


2
나는이 질문을 놓쳤다! 이 경고가 혼란스러워서 죄송합니다. 새로운 Node.js에서 실제로 개선했으며 모든 것을 훨씬 빨리 개선하고 있습니다!
Benjamin Gruenbaum


@BenjaminGruenbaum, 아직 수정 되었습니까? 노드 v12.16.1에서 동일한 오류가 발생했습니다.
Baby desta

1
@Babydesta는 스택 추적에서 더 나은 오류를 보여 주지만 처리되지 않은 거부에서 여전히 노드 충돌을 일으키지 않습니다. 아마도 PR을 열어야 할 것입니다.
Benjamin Gruenbaum

답변:


200

이 오류의 근원은 각각의 모든 약속이 약속 거부를 처리해야한다는 사실에 있습니다. 즉 .catch (...)가 있습니다. 아래 주어진 코드의 약속에 .catch (...) 를 추가하여 동일한 것을 피할 수 있습니다.

예를 들어, 함수 PTest ()는 전역 변수 somevar 의 값을 기반으로 약속을 해결하거나 거부합니다 .

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
}).catch(function () {
     console.log("Promise Rejected");
});

경우에 따라 약속되지 않은 .catch (..)가 있어도 "처리되지 않은 약속 거부" 메시지가 나타납니다. 코드 작성 방법에 관한 모든 것입니다. 다음 코드는 처리 하고 있지만 "처리되지 않은 약속 거부"를 생성 catch합니다.

var somevar = false;
var PTest = function () {
    return new Promise(function (resolve, reject) {
        if (somevar === true)
            resolve();
        else
            reject();
    });
}
var myfunc = PTest();
myfunc.then(function () {
     console.log("Promise Resolved");
});
// See the Difference here
myfunc.catch(function () {
     console.log("Promise Rejected");
});

차이점은 .catch(...)체인으로 취급하지 않고 별개로 처리한다는 것 입니다. 어떤 이유로 JavaScript 엔진은 처리되지 않은 약속 거부없이 약속으로 취급합니다.


4
myFunc = myFunct.then...두 번째 예 를 추가하면 효과가있는 것 같습니다 .
아인슈타인

@einstein 첫 번째 예에서와 동일한 체인을 다시 작성하기 때문에 작동하는 것처럼 보입니다.var x = foo(); x = x.then(...); x = x.catch(...)
randomsock

4
당신이 "취소 처리 약속을 거부하지 않고 약속과 같은 몇 가지 이유를 들어 자바 스크립트 엔진 취급은"말할 때 @einstein 당신의 연쇄 (unchained)의 예에서,이되지 않기 때문에 예외가에 던져 질 수 .then(() => {...})있는 당신이 되지 않습니다 처리? 나는 이것이 당신이 그들을 묶을 때와 똑같은 일을하고 있다고 생각하지 않습니다. 그렇습니까?
Simon Legg

8
@DKG 두 번째 요점 catch은에 대한 구문 설탕입니다 then(undefined, onRejected). myfunc에서 이미 호출 한 후 오류가 발생했기 때문에 동일한 약속에 대해 then (undefined, onRejected)을 다시 호출하지 않습니다.
Kevin Lee

1
어디서 변경해야합니까? 이온 코르도바 빌드 andorid 명령에이 오류가 발생하면 이온 3을 사용하고 있습니다.
Sagar Kodte

34

이것은 a Promise로 완료 .reject()되거나 async실행 코드 에서 예외가 발생 .catch()하고 거부를 처리 하지 않은 경우입니다.

거부 된 약속은 응용 프로그램 진입 점을 향해 버블 링되어 근본 오류 처리기가 해당 출력을 생성하는 예외와 같습니다.

또한보십시오


어디서 변경해야합니까? 이온 코르도바 빌드 andorid 명령에이 오류가 발생하면 이온 3을 사용하고 있습니다.
Sagar Kodte

이 정보를 말하기 어렵다. 최소한의 재생산을 만들고 특정 상황에 맞는 새로운 질문을 만들도록 제안합니다.
Günter Zöchbauer

나는 현상금을 개설했습니다. 그것을보십시오 stackoverflow.com/q/48145380/5383669
Sagar Kodte

22

약속은 거부 된 후에 "처리"될 수 있습니다. 즉, catch 처리기를 제공하기 전에 promise의 거부 콜백을 호출 할 수 있습니다. 이 행동은 쓸 수 있기 때문에 조금 귀찮습니다 ...

var promise = new Promise(function(resolve) {
kjjdjf(); // this function does not exist });

...이 경우 약속은 자동으로 거부됩니다. 캐치 핸들러 추가를 잊어 버린 경우에도 코드는 자동으로 오류없이 계속 실행됩니다. 이로 인해 느리고 찾기 어려운 버그가 발생할 수 있습니다.

Node.js의 경우, 이러한 처리되지 않은 Promise 거부를 처리하고 문제를보고하는 이야기가 있습니다. 이로 인해 ES7 async / await가 나타납니다. 이 예제를 고려하십시오.

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  let temp = await tempPromise;
  // Assume `changeClothes` also returns a Promise
  if(temp > 20) {
    await changeClothes("warm");
  } else {
    await changeClothes("cold");
  }

  await teethPromise;
}

위의 예에서 getRoomTemperature가 충족되기 전에 teethPromise가 거부되었다고 가정합니다 (오류 : 치약에서!). 이 경우 teethPromise를 기다릴 때까지 처리되지 않은 Promise 거부가 발생합니다.

내 요점은 ... 우리가 처리되지 않은 약속 거부를 문제로 생각하면 나중에 대기에 의해 처리되는 약속은 실수로 버그로보고 될 수 있습니다. 처리되지 않은 약속 거부가 문제가되지 않는 것으로 간주하면 합법적 인 버그가보고되지 않을 수 있습니다.

이것에 대한 생각?

이것은 Node.js 프로젝트의 토론과 관련이 있습니다.

처리되지 않은 기본 거부 감지 동작

이 방법으로 코드를 작성하는 경우 :

function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  return Promise.resolve(tempPromise)
    .then(temp => {
      // Assume `changeClothes` also returns a Promise
      if (temp > 20) {
        return Promise.resolve(changeClothes("warm"));
      } else {
        return Promise.resolve(changeClothes("cold"));
      }
    })
    .then(teethPromise)
    .then(Promise.resolve()); // since the async function returns nothing, ensure it's a resolved promise for `undefined`, unless it's previously rejected
}

getReadyForBed가 호출되면 최종 (반환되지 않은) 약속을 동기식으로 작성합니다.이 약속은 다른 약속과 동일한 "처리되지 않은 거부"오류가 있습니다 (물론 엔진에 따라 다를 수는 없음). (당신의 함수가 아무것도 반환하지 않는 것이 매우 이상합니다. 즉, 비동기 함수는 정의되지 않은 약속을 만듭니다.

캐치없이 지금 약속을하고 나중에 하나를 추가하면 나중에 처리 할 때 대부분의 "처리되지 않은 거부 오류"구현이 실제로 경고를 취소합니다. 다시 말해, async / await는 내가 볼 수있는 "처리되지 않은 거부"토론을 변경하지 않습니다.

이 함정을 피하려면 다음과 같이 코드를 작성하십시오.

async function getReadyForBed() {
  let teethPromise = brushTeeth();
  let tempPromise = getRoomTemperature();

  // Change clothes based on room temperature
  var clothesPromise = tempPromise.then(function(temp) {
    // Assume `changeClothes` also returns a Promise
    if(temp > 20) {
      return changeClothes("warm");
    } else {
      return changeClothes("cold");
    }
  });
  /* Note that clothesPromise resolves to the result of `changeClothes`
     due to Promise "chaining" magic. */

  // Combine promises and await them both
  await Promise.all(teethPromise, clothesPromise);
}

이는 처리되지 않은 약속 거부를 방지해야합니다.


13

"DeprecationWarning : 처리되지 않은 약속 거부는 더 이상 사용되지 않습니다"

TLDR :의 약속이 resolvereject하는 일을 reject당신이 가지고 적어도 할 것이다, 그래서이되지 않습니다 처리하는 캐치없이 catch최상위 수준.


2

필자의 경우 Promise 함수에서 예외가 발생했기 때문에 거부하지 않고 약속을 지키지 않은 Promise였습니다. 이 실수는 UnhandledPromiseRejectionWarning 메시지를 발생시킵니다.


1

약속을 인스턴스화하면 비동기 함수를 생성합니다. 함수가 제대로 진행되면 RESOLVE를 호출하면 THEN의 RESOLVE 처리기에서 흐름이 계속됩니다. 함수가 실패한 경우 REJECT를 호출하여 함수를 종료하면 CATCH에서 플로우가 계속됩니다.

NodeJ에서는 거부 처리기가 더 이상 사용되지 않습니다. 귀하의 오류는 경고 일 뿐이며 node.js github에서 읽습니다. 나는 이것을 찾았다.

DEP0018 : 처리되지 않은 약속 거부

유형 : 런타임

처리되지 않은 약속 거부는 더 이상 사용되지 않습니다. 앞으로 처리되지 않은 약속 거부는 0이 아닌 종료 코드로 Node.js 프로세스를 종료합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.