IT TIP

`.catch (err => console.error (err))`가 권장되지 않는 이유는 무엇입니까?

itqueen 2020. 12. 12. 12:53
반응형

`.catch (err => console.error (err))`가 권장되지 않는 이유는 무엇입니까?


약속을 사용하고 있으며 다음과 같은 코드가 있습니다.

function getStuff() { 
  return fetchStuff().then(stuff => 
    process(stuff)
  ).catch(err => {
    console.error(err);
  });
}

또는:

async function getStuff() { 
  try {
    const stuff = await fetchStuff();
    return process(stuff);
  } catch (err) { 
    console.error(err);
  }
}

오류 누락을 방지하기 위해이 작업을 수행했지만 동료 사용자로부터이 작업을하면 안된다는 말을 들었고 눈살을 찌푸 렸습니다.

  • 뭐가 잘못 return ….catch(err => console.error(err))됐나요?
  • 나는 이것을하는 많은 코드를 보았는데, 왜?
  • 대신 무엇을해야합니까?

왜 오래된 코드가 이것을합니까?

역사적으로 오래된 (2013 년 이전) 라이브러리는 사용자가 직접 처리하지 않은 처리되지 않은 약속 거부를 '삼켰다'고 약속했습니다. 그 이후로 쓰여진 어떤 것도 그렇지 않았습니다.

오늘은 어떻게 되나요?

브라우저와 Node.js는 이미 잡히지 않은 promise 거부를 자동으로 기록하거나이를 처리하기위한 동작을 가지고 있으며 자동으로 기록합니다.

또한-를 추가하여 반환 .catch되는 함수를 호출하는 메서드에 신호를 undefined보냅니다.

// undefined if there was an error
getStuff().then(stuff => console.log(stuff)); 

비동기 코드를 작성할 때 스스로 물어봐야 할 질문은 일반적으로 "코드의 동기 버전이 무엇을할까요?"입니다.

function calculate() { 
  try {
    const stuff = generateStuff();
    return process(stuff);
  } catch (err) { 
    console.error(err);
    // now it's clear that this function is 'swallowing' the error.
  }
}

소비자는 undefined오류가 발생하면 이 함수가 반환 될 것으로 기대하지 않습니다 .

요약하자면, 응용 프로그램 흐름에서 개발자를 놀라게하고 브라우저가 오늘 어쨌거나 잡히지 않은 약속 오류를 기록하기 때문에 눈살을 찌푸립니다.

대신 수행 할 작업 :

아무것도. 그것이 그것의 아름다움입니다-만약 당신이 쓴다면 :

async function getStuff() { 
  const stuff = await fetchStuff();
  return process(stuff);
}
// or without async/await
const getStuff = fetchStuff().then(process);

처음에는 어쨌든 더 나은 오류가 발생 합니다. :)

이전 버전의 Node.js를 실행중인 경우 어떻게해야합니까?

이전 버전의 Node.js는 오류를 기록하지 않거나 지원 중단 경고를 표시하지 않을 수 있습니다. 이러한 버전에서는 전역 적으로 사용할 수 있습니다 console.error(또는 적절한 로깅 계측) .

// or throw to stop on errors
process.on('unhandledRejection', e => console.error(e));

뭐가 잘못 return ….catch(err => console.error(err))됐나요?

undefined오류를 처리 한 후 이행 할 약속을 반환합니다 .

그 자체로 오류를 포착하고 로깅하는 것은 약속 체인의 끝에서 괜찮습니다.

function main() {
    const element = document.getElementById("output");
    getStuff().then(result => {
        element.textContent = result;
    }, error => {
        element.textContent = "Sorry";
        element.classList.add("error");
        console.error(error);
    });
    element.textContent = "Fetching…";
}

그러나 getStuff()오류 자체를 포착하여 로그를 기록하고 합리적인 대체 결과를 제공하는 것처럼 처리하기 위해 다른 작업을 수행하지 않으면 undefined" 죄송합니다 " 대신 페이지 표시됩니다 .

나는 이것을하는 많은 코드를 보았는데, 왜?

Historically, people were afraid of promise errors being handled nowhere which lead to them disappearing altogether - being "swallowed" by the promise. So they added .catch(console.error) in every function to make sure that they'd notice errors in the console.

This is no longer necessary as all modern promise implementation can detect unhandled promises rejections and will fire warnings on the console.

Of course it's still necessary (or at least good practice, even if you don't expect anything to fail) to catch errors at the end of the promise chain (when you don't further return a promise).

What should I do instead?

In functions that return a promise to their caller, don't log errors and swallow them by doing that. Just return the promise so that the caller can catch the rejection and handle the error appropriately (by logging or anything).

This also simplifies code a great lot:

function getStuff() { 
  return fetchStuff().then(stuff => process(stuff));
}

async function getStuff() { 
  const stuff = await fetchStuff();
  return process(stuff);
}

If you insist on doing something with the rejection reason (logging, amending info), make sure to re-throw an error:

function getStuff() { 
  return fetchStuff().then(stuff =>
    process(stuff)
  ).catch(error => {
    stuffDetails.log(error);
    throw new Error("something happened, see detail log");
  });
}

async function getStuff() {
  try {
    const stuff = await fetchStuff();
    return process(stuff);
  } catch(error) {
    stuffDetails.log(error);
    throw new Error("something happened, see detail log");
  }
}

Same if you are handling some of the errors:

function getStuff() { 
  return fetchStuff().then(stuff =>
    process(stuff)
  ).catch(error => {
    if (expected(error))
      return defaultStuff;
    else
      throw error;
  });
}

async function getStuff() {
  try {
    const stuff = await fetchStuff();
    return process(stuff);
  } catch(error) {
    if (expected(error))
      return defaultStuff;
    else
      throw error;
  }
}

The reason you should not catch errors unless absolutely required (which is never) is that

Apart from swallowing promise rejections, catch handler also swallows any JS errors that occurs in any successive code run by the corresponding success handler.

Implications

  1. Once an error is caught by a catch handler, it is considered as done and handled. All the successive promise subscribers in the promise chain will call their success handlers instead of failure or catch handlers. This leads to weird behaviours. This is never the intended code flow.

  2. If a function at lower level like a service method (getStuff) handles errors in catch, it breaks the principle of Separation of Concerns. A responsibility of service handler should be solely to fetch data. When that data call fails, the application who is calling that service handler should manage the error.

  3. The catching of error in some function being caught by another one, results in weird behaviours all around and makes it really hard to track root causes of bugs. To track such bugs we have to enable the Break on Caught Exceptions in the Chrome dev console which will break on every catch and could take hours at an end to debug.

It is always a good practice to handle promise rejections but We should always do that using failure handler over catch handler. A failure handler will only catch Promise rejections and lets the application break, if any JS error occurs, which is how it should be.


error is much too generic, it is a catch all but there are only so many things that the operation would fail with, error is everything errorSomethingSpecific gives granularity


The most general statement here, that applies in languages beyond javascript, is don't 'catch' an error unless you plan to 'handle' the error. Logging is not handling.

i.e. In general, the best (only?) reason for a catch is to handle/'deal with' the error in a constructive way that allows the code to carry on without any further problems. And again, a line of logging probably never achieves that...

참고URL : https://stackoverflow.com/questions/50896442/why-is-catcherr-console-errorerr-discouraged

반응형