조기 해결 / 거부 후 귀국해야합니까?


262

다음 코드가 있다고 가정하십시오.

function divide(numerator, denominator) {
 return new Promise((resolve, reject) => {

  if(denominator === 0){
   reject("Cannot divide by 0");
   return; //superfluous?
  }

  resolve(numerator / denominator);

 });
}

나의 목표가 reject일찍 퇴장하는 데 사용된다면 , return바로 후에도 습관을 섭취 해야 합니까?


5
그렇습니다. 실행 완료

답변:


371

return목적은 후에 제거 기능의 실행을 종료하고, 그 후, 코드의 실행을 방지하기위한 것이다.

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {

    if (denominator === 0) {
      reject("Cannot divide by 0");
      return; // The function execution ends here 
    }

    resolve(numerator / denominator);
  });
}

이 경우 resolve(numerator / denominator);엄격하게 필요하지 않은 실행을 방지 합니다. 그러나 향후 가능한 트랩을 방지하기 위해 실행을 종료하는 것이 여전히 바람직합니다. 또한 불필요하게 코드 실행을 방지하는 것이 좋습니다.

배경

약속은 3 가지 상태 중 하나 일 수 있습니다.

  1. 보류 중-초기 상태 보류 상태에서 다른 상태 중 하나로 이동할 수 있습니다
  2. 이행-성공적인 운영
  3. 거부 됨-작업 실패

약속이 이행되거나 거절 될 때,이 상태는 무기한 (정착)으로 유지됩니다. 따라서 약속 된 약속을 거부하거나 거부 된 약속을 이행해도 효과가 없습니다.

이 예제 스 니펫은 약속이 거부 된 후에도 이행되었지만 거부 된 상태임을 보여줍니다.

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
    }

    resolve(numerator / denominator);
  });
}

divide(5,0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));

그렇다면 왜 돌아와야합니까?

확정 된 약속 상태를 변경할 수는 없지만 거부하거나 해결해도 나머지 기능의 실행은 중지되지 않습니다. 이 함수에는 혼란스러운 결과를 생성하는 코드가 포함될 수 있습니다. 예를 들면 다음과 같습니다.

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) {
      reject("Cannot divide by 0");
    }
    
    console.log('operation succeeded');

    resolve(numerator / denominator);
  });
}

divide(5, 0)
  .then((result) => console.log('result: ', result))
  .catch((error) => console.log('error: ', error));

함수에 지금 그러한 코드가 포함되어 있지 않더라도 앞으로 가능한 함정이 생길 수 있습니다. 향후 리 팩터는 약속이 거부 된 후에도 코드가 여전히 실행되어 디버그하기 어렵다는 사실을 무시할 수 있습니다.

해결 / 거부 후 실행 중지 :

이것은 표준 JS 제어 흐름입니다.

  • resolve/ reject다음에 반환

  • 로 돌아 가기 resolve/ reject- 콜백의 반환 값이 무시되기 때문에, 우리는이 / 해결 문을 거부 반환하여 선을 절약 할 수 있습니다 :

  • if / else 블록 사용 :

return코드가 더 평평 하므로 옵션 중 하나를 사용하는 것을 선호합니다 .


28
return일단 약속 상태가 설정되면 코드를 변경할 수 없으므로 호출 resolve()후 호출 reject()하면 몇 가지 추가 CPU 사이클을 사용하는 것 외에는 아무것도 수행 되지 않기 때문에 코드가 실제로 다르게 작동 하지 않습니다. 나 자신 return은 코드 청결성과 효율성 관점에서이 코드를 사용 하지만이 특정 예에서는 필요하지 않습니다.
jfriend00

1
Promise.try(() => { })새로운 약속 대신 사용하고 시도 / 거부 전화를 사용하지 마십시오. 대신 당신은 return denominator === 0 ? throw 'Cannot divide by zero' : numerator / denominator; 내가 Promise.try약속을 시작하고 문제가있는 try / catch 블록에 싸인 약속을 제거하는 수단으로 사용 한다고 쓸 수 있습니다 .
kingdango

2
알아두면 좋으며 패턴이 마음에 듭니다. 그러나 현재 Promise.try 는 0 단계 제안이므로 shim 또는 bluebird 또는 Q와 같은 약속 라이브러리를 사용해야 만 사용할 수 있습니다 .
Ori Drori

6
@ jfriend00이 간단한 예제에서 코드는 다르게 동작하지 않습니다. 그러나 reject데이터베이스 또는 API 엔드 포인트에 연결하는 것과 같이 비싼 코드가 있다면 어떻게해야 합니까? 특히 AWS 데이터베이스 또는 API Gateway 엔드 포인트와 같은 것에 연결하는 경우에는 모든 것이 불필요하고 비용과 리소스 비용이 많이 듭니다. 이 경우 불필요한 코드가 실행되는 것을 피하기 위해 확실히 리턴을 사용합니다.
Jake Wilson

3
@JakeWilson-물론, 이것은 자바 스크립트의 정상적인 코드 흐름 일 뿐이며 약속과는 전혀 관련이 없습니다. 함수 처리를 마치고 현재 코드 경로에서 더 이상 코드를 실행하지 않으려면을 삽입하십시오 return.
jfriend00

37

또는 당신의 차 한잔하지 않을 수 있습니다 일반적인 관용구,의 결합하는 것입니다 return과를 reject함수의 나머지 부분이 포함되도록, 동시에 함수의 약속 종료를 거부하려면, resolve실행되지 않습니다. 이 스타일이 마음에 들면 코드를 좀 더 간결하게 만들 수 있습니다.

function divide(numerator, denominator) {
  return new Promise((resolve, reject) => {
    if (denominator === 0) return reject("Cannot divide by 0");
                           ^^^^^^^^^^^^^^
    resolve(numerator / denominator);
  });
}

약속 생성자는 어떤 리턴 값으로 아무것도하지 않으며, 어떠한 경우에도 때문에 잘 작동 resolve하고 reject반환 아무것도.

다른 답변에 표시된 콜백 스타일과 동일한 관용구를 사용할 수 있습니다.

function divide(nom, denom, cb){
  if(denom === 0) return cb(Error("Cannot divide by zero"));
                  ^^^^^^^^^
  cb(null, nom / denom);
} 

다시 말하지만, 호출하는 사람 divide은 아무것도 리턴하지 않고 리턴 값으로 아무것도하지 않기 때문에 제대로 작동합니다.


6
나는 이것이 싫다. 이것은 당신이 실제로 그렇지 않은 것을 돌려주고 있다는 생각을줍니다. 거부 함수를 호출 한 다음 return 키를 사용하여 함수 실행을 종료합니다. 그것들을 별도의 줄에 유지하십시오. 당신이하는 일은 사람들을 혼란스럽게 할 것입니다. 코드 가독성은 왕입니다.
K-SO의 독성이 증가하고 있습니다.

7
@KarlMorrison 당신은 사실 거부 된 약속 인 "뭔가"를 반환하고 있습니다. 당신이 말하는 "노션"은 매우 개인적이라고 생각합니다. reject상태 를 반환하는 데 아무런 문제가 없습니다
Frondor

5
@Frondor 나는 당신이 내가 쓴 것을 이해했다고 생각하지 않습니다. 물론 당신과 나는 이것을 이해하지만, 같은 줄에서 거부를 반환 할 때 아무 일도 일어나지 않습니다. 그러나 JavaScript가 프로젝트에 들어오는 데 익숙하지 않은 개발자는 어떻습니까? 이러한 유형의 프로그래밍은 그러한 사람들의 가독성을 감소시킵니다. 오늘날 JavaScript 에코 시스템은 엉망이며 이러한 유형의 관행을 퍼뜨리는 사람들은 그것을 악화시킬뿐입니다. 이것은 나쁜 습관입니다.
K-SO의 독성이 증가하고 있습니다.

1
@KarlMorrison 개인적인 의견! = 나쁜 습관. 새로운 Javascript 개발자가 수익에 어떤 일이 일어나고 있는지 이해하는 데 도움이 될 것입니다.
Toby Caulk

1
@TobyCaulk 사람들이 어떤 수익을 배워야한다면 약속을 가지고 놀아서는 안되며, 기본 프로그래밍을 배우는 것이 좋습니다.
K-SO의 독성이 증가하고 있습니다.

10

기술적으로 여기에서는 필요하지 않습니다. 1- 약속은 독점적으로 한 번만 해결 하거나 거부 할 수 있기 때문 입니다. 첫 번째 약속 결과가 승리하고 모든 후속 결과는 무시됩니다. 이것은 노드 스타일 콜백 과 다릅니다 .

즉 , 더 이상 비동기 / 지연된 처리가 없기 때문에 실제로는 실제로이 경우에는 정확히 하나가 호출되도록하는 것이 좋습니다 . "조기 반환"결정 은 작업이 완료되었을 때 기능을 종료하는 것과 관련이 있습니다.

적절한 시간에 돌아 오면 (또는 "다른"경우의 실행을 피하기 위해 조건부 사용) 실수로 코드를 유효하지 않은 상태로 실행하거나 원하지 않는 부작용을 수행 할 가능성을 줄입니다. 따라서 코드가 '예기치 않게 중단되는'경향이 줄어 듭니다.


1기술 답변은 이 경우 "반환"후의 코드를 생략해도 부작용이 발생하지 않는다는 사실에 달려 있습니다. JavaScript는 행복하게 0으로 나누고 + Infinity / -Infinity 또는 NaN을 반환합니다.


좋은 각주 !!
HankCa

9

해결 / 거부 후에 "반환"하지 않으면 페이지 리디렉션과 같은 나쁜 일이 발생했을 수 있습니다. 출처 : 나는 이것에 부딪쳤다.


6
예를 들어 +1입니다. 내 프로그램이 100 + 유효하지 않은 데이터베이스 쿼리를 만드는 문제가 있었고 그 이유를 알 수 없었습니다. 거부 후 "반환"하지 않은 것으로 나타났습니다. 작은 실수이지만 수업을 배웠습니다.
AdamInTheOculus

8

Ori의 답변은 이미 필요 return하지는 않지만 좋은 방법이라고 설명합니다. promise 생성자는 안전하게 던져 질 수 있으므로 나중에 경로에서 전달 된 예외를 무시합니다. 본질적으로 쉽게 관찰 할 수없는 부작용이 있습니다.

참고 return초기 보내고하는 콜백도 매우 일반적입니다 :

function divide(nom, denom, cb){
     if(denom === 0){
         cb(Error("Cannot divide by zero");
         return; // unlike with promises, missing the return here is a mistake
     }
     cb(null, nom / denom); // this will divide by zero. Since it's a callback.
} 

따라서 약속하는 것이 좋지만 콜백 이 필요합니다 . 코드에 대한 참고 사항 :

  • 유스 케이스는 가상이므로 실제로는 동기 조치와 함께 약속을 사용하지 마십시오.
  • 약속 생성자 반환 값을 무시 합니다. 정의되지 않은 값을 반환하면 반환되는 실수에 대해 경고하는 경우 일부 라이브러리가 경고합니다. 대부분은 영리하지 않습니다.
  • 약속 생성자는 안전하게 던져져 예외를 거부로 변환하지만 다른 사람들이 지적했듯이 약속은 한 번 해결됩니다.

4

대부분의 경우 매개 변수를 별도로 확인하고 Promise.reject (reason) 으로 거부 된 약속을 즉시 반환 할 수 있습니다.

function divide2(numerator, denominator) {
  if (denominator === 0) {
    return Promise.reject("Cannot divide by 0");
  }
  
  return new Promise((resolve, reject) => {
    resolve(numerator / denominator);
  });
}


divide2(4, 0).then((result) => console.log(result), (error) => console.log(error));

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