console.log () 비동기 또는 동기화?


93

현재 Trevor Burnham의 Async Javascript 를 읽고 있습니다. 이것은 지금까지 훌륭한 책이었습니다.

그는이 스 니펫과 console.log가 Safari 및 Chrome 콘솔에서 '비동기'라고 말합니다. 불행히도 나는 이것을 복제 할 수 없습니다. 다음은 코드입니다.

var obj = {}; 
console.log(obj); 
obj.foo = 'bar';
// my outcome: Object{}; 'bar';
// The book outcome: {foo:bar};

이것이 비동기 적이라면 결과가 책 결과가 될 것으로 예상합니다. console.log ()는 모든 코드가 실행될 때까지 이벤트 큐에 넣은 다음 실행되고 bar 속성을 갖게됩니다.

동 기적으로 실행되고 있지만 나타납니다.

이 코드를 잘못 실행하고 있습니까? console.log는 실제로 비동기입니까?


@thefourtheye : 아니요, 내 댓글을 삭제해야합니다.
쿠키 몬스터

1
나는 그것이 크롬에서 일어나는 것을 보았다. 간단한 개체를 console.log 한 다음 즉시 개체의 내용을 변경하면에 console.log()항상 이전 값이 표시되지는 않습니다. 이 문제가 발생하는 경우 해결 방법은 시도하려는 모든 것을 console.log()변경 불가능한 문자열 로 변환 하여이 문제의 영향을받지 않는 것입니다. 따라서 경험상 console.log()프로세스 경계를 ​​넘어 데이터를 마샬링하는 것과 관련된 비동기 문제가 있습니다. 이것은 의도 된 동작은 아니지만 console.log()내부적으로 작동 하는 방식 의 일부 부작용입니다 (개인적으로 버그라고 생각합니다).
jfriend00 2014


1
@bergi이 속임수를 찾는 데 10 분이 걸렸습니다 (정확한 이름은 알고 있었지만). 아마도 속임수로 닫 혔기 때문일 것입니다. 우리는 단지 복제물을 바꿔서 다른 하나가 속임수가되도록 할 수는 없습니까?
Jonas Wilms

1
@JonasWilms 이제이 질문을 다시 열었습니다 ( 역사 참조 ). 나는 그것들이 서로 중복된다고 생각하지 않는다. 나는 크롬의 자바 스크립트 콘솔이 배열을 평가하는 데 게으르다? 특히 어레이와 관련된 문제의 표준 대상으로 사용됩니다.
Bergi

답변:


114

console.log표준화되지 않았으므로 동작이 정의되지 않았으며 개발자 도구의 릴리스마다 쉽게 변경할 수 있습니다. 곧 제 답변처럼 귀하의 책은 구식 일 가능성이 있습니다.

우리 코드에서는 console.log비동기 여부와 상관없이 어떠한 종류의 콜백도 제공하지 않습니다. 전달하는 값은 항상 함수를 호출 할 때 참조되고 계산됩니다.

우리는 그때 무슨 일이 일어나는지 실제로 알지 못합니다 (좋습니다. Firebug, Chrome Devtools 및 Opera Dragonfly는 모두 오픈 소스이기 때문에 가능합니다). 콘솔은 기록 된 값을 어딘가에 저장해야하며 화면에 표시합니다. 렌더링은 확실하게 비동기식으로 발생하며 (속도 제한 업데이트로 제한됨) 콘솔에 로깅 된 개체와의 향후 상호 작용 (예 : 확장 개체 속성)이 마찬가지입니다.

따라서 콘솔은 로그 한 변경 가능한 객체를 복제 (직렬화)하거나 참조를 저장할 수 있습니다. 첫 번째는 깊고 큰 물체에서는 잘 작동하지 않습니다. 또한 적어도 콘솔의 초기 렌더링은 아마도 객체의 "현재"상태를 보여줄 것입니다. 즉, 로그인했을 때의 상태를 보여줄 것입니다 Object {}.

그러나 속성을 추가로 검사하기 위해 개체를 확장하면 콘솔에 개체 및 해당 속성에 대한 참조 만 저장 될 가능성이 높으며 지금 표시하면 현재 (이미 변경된) 상태가 표시됩니다. 를 클릭 +하면 bar예제 에서 속성 을 볼 수 있습니다 .

다음 은 "수정"을 설명하기 위해 버그 보고서 에 게시 된 스크린 샷입니다 .

따라서 일부 값은 기록 된 후 오랫동안 참조 될 수 있으며 이러한 값의 평가는 다소 립니다 ( "필요할 때"). 이 불일치의 가장 유명한 예 는 Chrome의 JavaScript 콘솔이 배열 평가에 대해 게으른가요? 라는 질문에서 처리됩니다 .

해결 방법은 객체의 직렬화 된 스냅 샷을 항상 기록하는 것 console.log(JSON.stringify(obj))입니다 ( 예 : . 그러나 이것은 원형이 아닌 작은 물체에만 작동합니다. Safari에서 console.log의 기본 동작을 어떻게 변경할 수 있습니까?를 참조하십시오 . .

더 나은 솔루션은 디버깅에 중단 점을 사용하는 것입니다. 여기서 실행이 완전히 중지되고 각 지점에서 현재 값을 검사 할 수 있습니다. 직렬화 가능하고 변경 불가능한 데이터에만 로깅을 사용하십시오.


2
console.log가 비동기가 아닌 것과 동일한 문제가 발생했습니다. JSON.stringify 나를 위해 그것을 고정 사용
russiansummer

2019 년 현재 console.logChrome에서 8 년이 지났기 때문에 여전히 비동기식 이라고 말할 수 있습니까 ( stackoverflow.com/questions/7389069/… 참조 ), 변경되는 유일한 점은 이제 Chrome이 참조 객체의 스냅 샷을 호출 할 때 console.log(기록 된 객체를 확장하면 이후에 수행 한 변형 작업 후에 최종 속성과 값이 console.log표시됨) 또는 console.log실제로 동기식입니까?
tonix

@tonix 예,이 동작은 내 대답에 명시된 이유 때문에 변경되지 않을 것입니다. 버그가 아니라 인터랙티브 디버거 / 검사기가 작동하는 방식입니다.
Bergi

여기JSON.parse(JSON.stringify(obj)) 주석 에서 언급 한대로 사용 하면 문자열 대신 객체 형식의 스냅 샷을 얻을 수 있습니다.
Wilt

TL, DR.way 방법 TL
Rick O'Shea

2

이것은 실제로 질문에 대한 답은 아니지만이 게시물을 우연히 발견 한 사람에게는 유용 할 수 있으며 댓글을 달기에는 너무 길었습니다.

window.console.logSync = (...args) => {
  try {
    args = args.map((arg) => JSON.parse(JSON.stringify(arg)));
    console.log(...args);
  } catch (error) {
    console.log('Error trying to console.logSync()', ...args);
  }
};

이것은의 의사 동기 버전을 생성 console.log하지만 수락 된 답변에서 언급 한 것과 동일한 경고가 있습니다.

현재 대부분의 브라우저 console.log는 어떤 방식 으로든 비동기식 인 것처럼 보이므로 특정 시나리오에서 이와 같은 기능을 사용하는 것이 좋습니다.


0

console.log를 사용하는 경우 :

a = {}; a.a=1;console.log(a);a.b=function(){};
// without b
a = {}; a.a=1;a.a1=1;a.a2=1;a.a3=1;a.a4=1;a.a5=1;a.a6=1;a.a7=1;a.a8=1;console.log(a);a.b=function(){};
// with b, maybe
a = {}; a.a=function(){};console.log(a);a.b=function(){};
// with b

첫 번째 상황에서 객체는 충분히 단순하므로 콘솔은이를 '문자열 화'하여 표시 할 수 있습니다. 그러나 다른 상황에서는 a가 'stringify'하기에는 너무 '복잡'하므로 콘솔은 대신 메모리 개체를 표시하고 예를 보면 b가 이미 a에 연결되어 있습니다.


나는이 질문이 3 살이라는 것을 알고 있지만 지금은 같은 문제를 겪고 있습니다. 너무 복잡하기 때문에 객체를 직렬화하는 것이 작동하지 않습니다. 데이터에 액세스하려는 이벤트를 잡았지만 어떻게 든 코드에 데이터가 없지만 console.log에는 데이터가 있습니다.
Skeec 2017-06-14
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.