programing

JavaScript 약속 - 거부 vs. throw

bestcode 2023. 1. 12. 22:13
반응형

JavaScript 약속 - 거부 vs. throw

이 몇 , 이 에 대한 하지 않습니다.Promise.reject 투척 vs. 를 들어 ,

Promise 사용거절하다

return asyncIsPermitted()
    .then(function(result) {
        if (result === true) {
            return true;
        }
        else {
            return Promise.reject(new PermissionDenied());
        }
    });

던지기 사용

return asyncIsPermitted()
    .then(function(result) {
        if (result === true) {
            return true;
        }
        else {
            throw new PermissionDenied();
        }
    });

는 가가제 my my my 를 사용하는 것이 좋습니다.throw그것은 단지 짧기 때문에, 그러나 다른 것에 비해 하나의 장점이 있는지 궁금했다.

한쪽과 다른 한쪽을 사용하는 이점은 없지만 다음과 같은 특별한 경우가 있습니다.throw작동하지 않습니다.이치노릇을 하다

든지 " " " 를 사용할 수 .throw 다른 에는 ', '다'를 reject.

예를 들어, 이렇게 해도 캐치가 트리거되지 않습니다.

new Promise(function() {
  setTimeout(function() {
    throw 'or nah';
    // return Promise.reject('or nah'); also won't work
  }, 1000);
}).catch(function(e) {
  console.log(e); // doesn't happen
});

대신 당신은 해결되지 않은 약속과 포착되지 않은 예외로 남게 된다. 대신 '어울리지 않다'를 사용하고 입니다.reject그러나 두 가지 방법으로 해결할 수 있습니다.

  1. 타임아웃 내에 원래 Promise의 거부 기능을 사용하여 다음을 수행합니다.

new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject('or nah');
  }, 1000);
}).catch(function(e) {
  console.log(e); // works!
});

  1. 타임아웃을 프로미스화함으로써

function timeout(duration) { // Thanks joews
  return new Promise(function(resolve) {
    setTimeout(resolve, duration);
  });
}

timeout(1000).then(function() {
  throw 'worky!';
  // return Promise.reject('worky'); also works
}).catch(function(e) {
  console.log(e); // 'worky!'
});

하나의 은 '우리'가 '우리'는reject() 제어 플로우는 다음과 같이 종료되지 않습니다.return스테이트먼트는 그렇습니다.로 ★★★★★★★★★★★★★★★★★★」throw는 제어 플로우를 종료합니다.

예:

new Promise((resolve, reject) => {
  throw "err";
  console.log("NEVER REACHED");
})
.then(() => console.log("RESOLVED"))
.catch(() => console.log("REJECTED"));

new Promise((resolve, reject) => {
  reject(); // resolve() behaves similarly
  console.log("ALWAYS REACHED"); // "REJECTED" will print AFTER this
})
.then(() => console.log("RESOLVED"))
.catch(() => console.log("REJECTED"));

네, 가장 큰 차이점은 거부가 약속이 거부된 후에 실행되는 콜백 함수인 반면 슬로우는 비동기적으로 사용할 수 없다는 것입니다.reject를 선택한 경우 코드는 비동기 방식으로 계속 정상적으로 실행되지만 throw는 리졸바 함수의 완료를 우선시합니다(이 함수는 즉시 실행됩니다).

문제를 명확히 하는 데 도움이 되는 예로는 다음과 같이 Reject를 사용하여 Timeout 함수를 설정할 수 있습니다.

new Promise((resolve, reject) => {
  setTimeout(()=>{reject('err msg');console.log('finished')}, 1000);
  return resolve('ret val')
})
.then((o) => console.log("RESOLVED", o))
.catch((o) => console.log("REJECTED", o));

위의 내용은 투척으로는 쓸 수 없습니다.

try{
  new Promise((resolve, reject) => {
    setTimeout(()=>{throw new Error('err msg')}, 1000);
    return resolve('ret val')
  })
  .then((o) => console.log("RESOLVED", o))
  .catch((o) => console.log("REJECTED", o));
}catch(o){
  console.log("IGNORED", o)
}

OP의 작은 예에서는 구별할 수 없지만 더 복잡한 비동기 개념을 다룰 때는 두 가지 사이의 차이가 확연할 수 있습니다.

TLDR: 함수는 약속을 반환하거나 예외를 발생시킬 때 사용하기 어렵습니다.비동기 함수를 쓸 때는 거부된 약속을 반환하여 실패를 알리는 것을 선호합니다.

이 예에서는 이들 간의 중요한 차이를 몇 가지 알 수 없습니다.

약속 체인 내에서 오류를 처리하고 있기 때문에, 느려진 예외는 거부된 약속으로 자동 변환됩니다.이것은 왜 그것들이 서로 교환 가능한 것처럼 보이는지 설명할 수 있지만, 그렇지 않다.

다음 상황을 고려하십시오.

checkCredentials = () => {
    let idToken = localStorage.getItem('some token');
    if ( idToken ) {
      return fetch(`https://someValidateEndpoint`, {
        headers: {
          Authorization: `Bearer ${idToken}`
        }
      })
    } else {
      throw new Error('No Token Found In Local Storage')
    }
  }

이는 비동기 오류와 동기 오류 사례를 모두 지원해야 하기 때문에 안티패턴이 될 수 있습니다.다음과 같은 경우가 있습니다.

try {
  function onFulfilled() { ... do the rest of your logic }
  function onRejected() { // handle async failure - like network timeout }
  checkCredentials(x).then(onFulfilled, onRejected);
} catch (e) {
  // Error('No Token Found In Local Storage')
  // handle synchronous failure
} 

좋지 않아. 여기가 바로 여기야.Promise.rejectscope )는, 됩니다( 「 」 、 「 」 、 「 」 、 「 」 、 「 」throw츠키다

checkCredentials = () => {
  let idToken = localStorage.getItem('some_token');
  if (!idToken) {
    return Promise.reject('No Token Found In Local Storage')
  }
  return fetch(`https://someValidateEndpoint`, {
    headers: {
      Authorization: `Bearer ${idToken}`
    }
  })
}

만 쓸 수요.catch()네트워크 장애 및 토큰 부족에 대한 동기 오류 체크:

checkCredentials()
      .catch((error) => if ( error == 'No Token' ) {
      // do no token modal
      } else if ( error === 400 ) {
      // do not authorized modal. etc.
      }

다른 답변에서는 다루지 않은1가지 차이점이 있습니다.따라서 다음과 같습니다.

가 에 된 then 그 , " " " 에 반환됩니다.then던져진 것과 함께 거부당합니다.

약속을 된 then는 이 약속에 따라 해결됩니다(그리고 최종적으로 거부됩니다).이 약속에서는 비동기 "틱"이 1개 추가될 수 있습니다(마이크로태스크 큐에 루프 1개를 추가하여 브라우저 용어로 변환합니다).

단, 이 차이에 의존하는 코드는 기본적으로 파손됩니다. :-) 약속의 이행 타이밍에 그다지 민감해서는 안 됩니다.

다음은 예를 제시하겠습니다.

function usingThrow(val) {
    return Promise.resolve(val)
        .then(v => {
            if (v !== 42) {
                throw new Error(`${v} is not 42!`);
            }
            return v;
        });
}
function usingReject(val) {
    return Promise.resolve(val)
        .then(v => {
            if (v !== 42) {
                return Promise.reject(new Error(`${v} is not 42!`));
            }
            return v;
        });
}

// The rejection handler on this chain may be called **after** the
// rejection handler on the following chain
usingReject(1)
.then(v => console.log(v))
.catch(e => console.error("Error from usingReject:", e.message));

// The rejection handler on this chain may be called **before** the
// rejection handler on the preceding chain
usingThrow(2)
.then(v => console.log(v))
.catch(e => console.error("Error from usingThrow:", e.message));

이것을 실행하면, 이 글에서 다음과 같이 입력합니다.

사용 오류던지기: 2는 42가 아니다!Reject 사용 오류: 1은 42가 아닙니다!

순서를 적어 둡니다.

해도 둘 다 체인을 사용하고 있습니다.usingThrow:

function usingThrow(val) {
    return Promise.resolve(val)
        .then(v => {
            if (v !== 42) {
                throw new Error(`${v} is not 42!`);
            }
            return v;
        });
}

usingThrow(1)
.then(v => console.log(v))
.catch(e => console.error("Error from usingThrow:", e.message));

usingThrow(2)
.then(v => console.log(v))
.catch(e => console.error("Error from usingThrow:", e.message));

이는 거부 핸들러가 다른 순서로 실행되었음을 나타냅니다.

사용 오류던지기: 1은 42가 아니다!사용 오류던지기: 2는 42가 아니다!

위에서 말한 "아마"는 다른 분야에서는 관련된 모든 약속이 네이티브 약속일 경우(그때뿐 아니라) 다른 유사한 상황에서 이 불필요한 체크 표시를 제거하는 작업이 있었기 때문입니다.(구체적으로는:async 「」입니다.return await x에는 비동기 체크와 비동기 체크가 추가되어 있습니다. return x으로써 ES2020의 경우,x다른 차이가 없는 경우에는 추가 체크 표시가 삭제됩니다.)

다시 말하지만 약속의 이행 시기에 민감한 코드는 이미 깨져 있습니다.그러니까 그건 정말 중요하지 않아요.

다른 답변에서 언급한 바와 같이 실질적인 용어로 다음과 같습니다.

그 외에는 대부분 스타일/선호도의 문제이기 때문에 대부분의 문제와 마찬가지로 팀원들과 무엇을 할 것인지(어느 쪽이든 상관없다)에 동의하고 일관성을 유지해야 합니다.

시험해 볼 수 있는 예.isVersion만 변경던지기 대신 거부를 사용하려면 false로 던집니다.

const isVersionThrow = true

class TestClass {
  async testFunction () {
    if (isVersionThrow) {
      console.log('Throw version')
      throw new Error('Fail!')
    } else {
      console.log('Reject version')
      return new Promise((resolve, reject) => {
        reject(new Error('Fail!'))
      })
    }
  }
}

const test = async () => {
  const test = new TestClass()
  try {
    var response = await test.testFunction()
    return response 
  } catch (error) {
    console.log('ERROR RETURNED')
    throw error 
  }  
}

test()
.then(result => {
  console.log('result: ' + result)
})
.catch(error => {
  console.log('error: ' + error)
})

차이는 3진 연산자

  • 사용할 수 있습니다.
return condition ? someData : Promise.reject(new Error('not OK'))
  • 사용할 수 없습니다.
return condition ? someData  : throw new Error('not OK')

언급URL : https://stackoverflow.com/questions/33445415/javascript-promises-reject-vs-throw

반응형