Fabrício의 대답은 바로 그 자리에 있습니다. 그러나 나는 그의 대답을 덜 기술적 인 것으로 보완하고 싶었다. 이것은 비 동시성의 개념을 설명하기 위해 유추에 초점을 둔다 .
유추 ...
어제, 내가하고있는 일에는 동료의 정보가 필요했습니다. 나는 그를 울렸다. 대화 방법은 다음과 같습니다.
나 : 안녕하세요 밥, 나는 우리가 어떻게 알 필요가 foo는 'D를 바 '지난 주 거라고. Jim은 이에 대한 보고서를 원하며 귀하는 이에 대한 세부 사항을 아는 유일한 사람입니다.
Bob : 물론이지만 30 분 정도 걸릴까요?
나 : 잘 했어. 정보를 받으면 다시 연락주세요!
이 시점에서 나는 전화를 끊었다. 보고서를 완성하기 위해 Bob의 정보가 필요했기 때문에 보고서를 남기고 커피를 마시 러 갔다가 이메일을 받았습니다. 40 분 후 (밥이 느리다) 밥이 전화를 걸어 필요한 정보를 주었다. 이 시점에서 필요한 모든 정보를 얻었으므로 보고서 작업을 다시 시작했습니다.
대화가 대신 이런 식으로 진행되었다고 상상해보십시오.
나 : 안녕하세요 밥, 나는 우리가 어떻게 알 필요가 foo는 'D를 바 '지난 주 거라고. Jim은 이에 대한 보고서를 원하며 이에 대한 세부 정보를 알고있는 유일한 사람입니다.
Bob : 물론이지만 30 분 정도 걸릴까요?
나 : 잘 했어. 기다릴게.
그리고 나는 거기에 앉아 기다렸다. 그리고 기다렸다. 그리고 기다렸다. 40 분 동안. 기다리는 것 외에는 아무것도하지 않습니다. 결국 밥은 나에게 정보를 주었고, 우리는 끊었고 보고서를 완성했다. 그러나 나는 40 분의 생산성을 잃었습니다.
이것은 비동기 대 동기 동작입니다.
이것이 바로 우리 질문의 모든 예에서 일어나는 일입니다. 이미지 로딩, 디스크에서 파일 로딩 및 AJAX를 통한 페이지 요청은 모두 느리게 작동합니다 (현대 컴퓨팅의 맥락에서).
JavaScript는 이러한 느린 작업이 완료 되기를 기다리지 않고 느린 작업이 완료 될 때 실행될 콜백 함수를 등록 할 수 있도록합니다. 그러나 그 동안 JavaScript는 다른 코드를 계속 실행합니다. 느린 작업이 완료되기를 기다리는 동안 JavaScript가 다른 코드 를 실행한다는 사실 은 동작을 비동기 적으로 만듭니다 . JavaScript가 다른 코드를 실행하기 전에 작업이 완료 될 때까지 기다렸다면 이는 동기 동작 일 것입니다.
var outerScopeVar;
var img = document.createElement('img');
// Here we register the callback function.
img.onload = function() {
// Code within this function will be executed once the image has loaded.
outerScopeVar = this.width;
};
// But, while the image is loading, JavaScript continues executing, and
// processes the following lines of JavaScript.
img.src = 'lolcat.png';
alert(outerScopeVar);
위의 코드에서 JavaScript를로드하도록 요청 lolcat.png
하고 있습니다. 이는 sloooow 작업입니다. 이 느린 작업이 완료되면 콜백 함수가 실행되지만 그 동안 JavaScript는 다음 코드 줄을 계속 처리합니다. 즉 alert(outerScopeVar)
.
이것이 경고가 표시되는 이유입니다 undefined
. (가) 이후 alert()
즉시 처리보다는 이미지를로드 한 후.
코드를 수정하려면 alert(outerScopeVar)
코드 를 콜백 함수 로 옮기면 됩니다. 결과적으로 더 이상 outerScopeVar
전역 변수로 선언 된 변수 가 필요하지 않습니다 .
var img = document.createElement('img');
img.onload = function() {
var localScopeVar = this.width;
alert(localScopeVar);
};
img.src = 'lolcat.png';
당신은 것입니다 항상 그 몇 가지 코드를 정의하는 자바 스크립트에서 유일하게 * 방법이기 때문에, 콜백은 함수로 지정되어 볼 수 있지만, 나중에까지 그것을 실행할 수 없습니다.
따라서 모든 예제 function() { /* Do something */ }
에서 콜백은 콜백입니다. 모든 예제 를 수정 하려면 작업의 응답이 필요한 코드를 여기로 옮기면됩니다!
* 기술적 eval()
으로도 사용할 수 있지만 이 목적 eval()
에는 악의적 입니다
발신자를 대기 상태로 유지하려면 어떻게합니까?
현재 이와 비슷한 코드가있을 수 있습니다.
function getWidthOfImage(src) {
var outerScopeVar;
var img = document.createElement('img');
img.onload = function() {
outerScopeVar = this.width;
};
img.src = src;
return outerScopeVar;
}
var width = getWidthOfImage('lolcat.png');
alert(width);
그러나 지금 우리는 그 return outerScopeVar
일이 즉시 일어난다 는 것을 알고 있습니다 . onload
콜백 함수가 변수를 업데이트 하기 전에 이 리드 getWidthOfImage()
반환 undefined
, 및 undefined
경고되고.
이 문제를 해결하려면 함수 호출 getWidthOfImage()
이 콜백을 등록한 다음 해당 콜백 내에 있도록 너비의 경고를 이동해야합니다.
function getWidthOfImage(src, cb) {
var img = document.createElement('img');
img.onload = function() {
cb(this.width);
};
img.src = src;
}
getWidthOfImage('lolcat.png', function (width) {
alert(width);
});
... 전과 같이 전역 변수 (이 경우 width
) 를 제거 할 수있었습니다 .