简体   繁体   English

通过AJAX请求创建图像后等待图像加载

[英]Wait for images to load after creating them via an AJAX request

I am getting images (74 files) with an AJAX request. 我正在通过AJAX请求获取图像(74个文件)。 I am loading them in to an array. 我正在将它们加载到数组中。 Then I change some style calling the function changeMargins() . 然后,我更改一些样式,调用函数changeMargins() The issue is that the function is called when the images are not yet all loaded and ready. 问题在于,当图像尚未全部加载并准备就绪时,将调用该函数。

imageArray = new Array();     

$.ajax({
  url: url,
  success: function (data) {
    counter = 0
    $(data).find("a").attr("href", function (i, val) {
      if (val.match(/\.(jpe?g|png|GIF)$/)) { 
        imageArray[counter]= new imageItem(url + val)
        ++counter;  
      }
    });

    changeMargins(imageArray);

How can I wait for completion of the AJAX and all load events on the Image elements and then continue processing? 如何等待AJAX​​的完成以及 Image元素上的所有加载事件,然后继续处理?

This problem is probably best addressed by "promisifying" the image loading process, ie create a promise that resolves when the images have loaded. 可以通过“使”图像加载过程“有保证”来最好地解决该问题,即创建一个在图像加载时解决的承诺。

There's a design decision to be made ... whether (a) to swallow load errors or (b) to allow any individual error to cause the whole process to fail. 有一个设计决定要做出……是(a)吞下负载错误,还是(b)允许任何单个错误导致整个过程失败。

Assuming (a), you would write something like this : 假设(a),您将编写如下内容:

function loadImages() {
    return $.ajax({
        url: url,
        // other ajax params?
    }).then(function(data) {
        return $.Deferred(function(dfrd) { // promisify the entire image loading proceess
            var imageArray = [];
            var counter = 0; // tally of images that have either loaded or failed to load
            $(data).find('a').get().map(function(element) {
                // map a elements in data to an array of their hrefs
                return element.href;
            }).filter(function (href) {
                // filter out any non-jpe?g|png|GIF 
                return href.match(/\.(jpe?g|png|GIF)$/);
            }).forEach(function(val) {
                // for each match, create a Image() object, push onto the array, attach onload and onerror handlers, and set the `src` attribute.
                var img = new Image();
                imageArray.push(img);
                img.onload = function loadHandler() {
                    counter += 1;
                    if(counter == images.length) {
                        dfrd.resolve(imageArray);
                    }
                };
                img.onerror = function errorHandler() {
                    console.log(new Error('image ' + url + val + ' failed to load'));
                    // Here, you might choose to splice failed Images out of `imageArray`.
                    counter += 1;
                    if(counter == images.length) {
                        dfrd.resolve(imageArray);
                    }
                };
                img.src = url + val;
            });
        });
    }).then(function(imageArray) {
        changeMargins(imageArray);
        return imageArray;
    });
}

Notes: 笔记:

  • More typically, one would choose to promisify at the lowest level (ie each Image() individually) but promises are fairly expensive, therefore with 74 images, it's better to promisify en masse . 更典型的,一个会选择在最低水平(即每个图像()单独),以promisify但承诺是相当昂贵的,因此与74倍的图像,这是更好地promisify 集体
  • By promisifying, and returning a promise from loadImages() , its caller is informed of completion of the process - you can chain loadImages().then(...) and do stuff when the images have loaded/failed. 通过承诺,并从loadImages()返回一个loadImages() ,它的调用者被告知该过程已完成-您可以链接loadImages().then(...)并在图像加载/失败时进行处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM