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
) 를 제거 할 수있었습니다 .