맨체스터 유나이티드와 맨체스터 시티의 지역 더비를 본 후, 예상되는 전국 더비를 볼 수 있으려면 아직 두 시간이나 남았습니다. 너무 심심하고 할 일도 없어서 놀러 포럼에 왔습니다. 이미지 사전 로딩에 대한 블로그 게시물을 봤는데 코드는 다음과 같습니다.
function loadImage(url, callback) {
var img = new Image(); //이미지를 미리 다운로드하기 위한 Image 객체 생성
img.src = url; (img.complete) { // 이미지가 브라우저 캐시에 이미 존재하는 경우 콜백 함수를 직접 호출합니다.
callback(img)
// onload 이벤트를 처리하지 않고 직접 반환합니다.
}
img.onload = function () { //이미지 다운로드 시 콜백 함수를 비동기적으로 호출합니다.
callback(img);
};
};
인터넷에서 관련 기사를 찾아보니 대체적으로 이런 생각이더군요.
이 방법의 기능은 괜찮지만 몇 가지 숨겨진 위험이 있습니다.
1 이미지의 onload 이벤트 핸들러로 임시 익명 함수를 생성하여 클로저를 형성합니다.
IE의 메모리 누수 패턴에 대한 기사를 모두 보셨을 것입니다. 패턴 중 하나는 순환 참조이며 클로저는 (스코프 체인 구현에 따라) 외부 운영 환경을 저장할 수 있으므로 img. onload 함수는 순환 참조를 형성하고 메모리 누수를 일으키는 img에 대한 참조도 저장합니다. (이 메모리 누수 모드는 IE6 하위 버전에만 존재합니다. 패치된 IE6 및 IE 상위 버전에서는 순환 참조로 인한 메모리 누수 문제가 해결되었습니다.)
2는 정적 이미지 로딩만 고려하고, onload를 여러 번 실행할 수 있는 gif와 같은 동적 이미지는 무시합니다.
위의 두 가지 문제를 해결하는 방법은 매우 간단합니다. 코드는 다음과 같습니다.
img.onload = function() {
//이미지 다운로드 시 콜백 함수를 비동기적으로 호출합니다.
img.onload = null;
callback(img) };
이는 메모리 누수 문제를 해결할 뿐만 아니라 동적 그림의 다중 트리거 문제도 방지할 수 있습니다. 이벤트.
일부 관련 블로그 게시물에서는 img.onload를 null로 설정해야 한다고 지적한 경우도 있는데, 대부분의 기사에서는 콜백 실행 후 img.onload를 null로 설정하여 문제를 해결할 수 있습니다. 순환 참조 문제가 있지만 동적 그림의 경우 콜백 실행에 시간이 많이 걸리면 여전히 여러 번 트리거될 위험이 숨겨져 있습니다.
위의 수정 후 숨겨진 위험은 제거되었지만 이 코드에는 여전히 최적화의 여지가 있습니다.
if (img.complete) {
// 이미지가 이미 브라우저 캐시에 있는 경우 콜백 함수
callback(img)>를 직접 호출합니다. return; // onload 이벤트 처리 없이 바로 return
}
해당 코드에 대해서는 해당 블로그 포스팅의 설명을 읽어보시기 바랍니다.
테스트 후. 여러 브라우저 버전에서 IE 및 Opera에서는 이미지가 한 번 로드된 후 이미지에 대한 다른 요청이 있는 경우 브라우저가 이미 이미지를 캐시했기 때문에 새 요청을 시작하지 않고 직접 로드하는 것으로 나타났습니다. 캐시에서 와. Firefox 및 Safari의 경우 두 가지 로딩 방법을 사용자에게 투명하게 만들려고 시도하며 이로 인해 이미지의 onload 이벤트도 발생합니다. 그러나 IE 및 Opera는 이 ID를 무시하고 이미지의 onload 이벤트를 발생시키지 않습니다. 위의 코드는 그 안에서 효과를 얻을 수 없습니다.
실제로 IE와 Opera에서는 캐시된 이미지의 초기 상태가 Firefox, Safari, Chrome에서와 다릅니다(관심이 있는 경우 다른 브라우저에서 테스트하고 img를 제공할 수 있습니다. 이전에 img의 상태 src에는 캐시된 이미지의 URL이 할당되지만 onload 이벤트의 트리거는 브라우저에 관계없이 일관됩니다. 이 문제의 근본 원인은 img의 src 값과 onload 이벤트의 바인딩 순서가 잘못된 것입니다(IE 및 Opera에서는 이미지가 캐시되기 때문에 src가 먼저 할당된 다음 onload가 할당되고 onload 이벤트가 할당됩니다). 놓쳤습니다). 먼저 onload 이벤트를 바인딩한 다음 src에 값을 할당해야 합니다. 코드는 다음과 같습니다.
function loadImage(url, callback) {
var img = new Image() //이미지를 미리 다운로드하기 위한 Image 객체 생성
img.onload = function(){
img .onload = null;
callback(img);
}
img.src = url
}
이렇게 하면 메모리 누수가 발생하고 동적 이미지가 발생합니다. 로딩 문제가 해결되었으며 콜백 호출을 구현하는 통합된 방법도 제공됩니다.