Javascript 在用数据填充json文件之前等待加载所有图像的正确方法

Javascript 在用数据填充json文件之前等待加载所有图像的正确方法,javascript,jquery,json,image,onload,Javascript,Jquery,Json,Image,Onload,因此,我有以下问题: 我有一个getJson方法,其中我使用for循环和不同的操作来用数据填充另一个json。在这个循环中,我尝试获取所有图像文件的维度(存储在第一个json中,带有src),并将它们作为另一个属性添加到第二个json中。 为此,我使用以下代码: $.getJSON("json.txt", function(myJsonData) { var elemID, elemType, elemURL, thumb, date, menuItem, imgH, img

因此,我有以下问题: 我有一个getJson方法,其中我使用for循环和不同的操作来用数据填充另一个json。在这个循环中,我尝试获取所有图像文件的维度(存储在第一个json中,带有src),并将它们作为另一个属性添加到第二个json中。 为此,我使用以下代码:

 $.getJSON("json.txt", function(myJsonData) {
         var elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW;

         for (key in myJsonData) {

             /*---Some operations for giving values all the variables---*/

             //Getting image dimensions
             var tempImg = new Image();
             tempImg.onload = function() {
                 imgW = this.width;
                 imgH = this.height;
                 console.log(imgW + 'x' + imgH);
                 loaded += 1;
             }
             tempImg.src = elemURL;

             //Filling the new json
             var newJsonData = {
                 "elemID": 'elemID_' + elemID,
                 "type": elemType,
                 "url": elemURL,
                 "thumbnail": thumb,
                 "menuItem": menuItem,
                 "date": date,
                 "W": imgW,
                 "H": imgH
             }
         }
     }
之后,我有一个函数来生成html代码,用于创建页面的dom。
问题是-新的json没有等待onload函数,我无法传递图像的维度。我正在考虑使用超时或其他方法,但我不确定这是否是一种好的做法。:/希望你们能提供帮助。

尝试创建一个包含
newJsonData
的jQuery延迟对象数组,其中定义了
newJsonData
,并在
img
onload
处理程序中解析延迟对象;从包含延迟对象数组的
$.getJSON()
返回新的承诺对象

注意,不确定在哪里

var elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW;
是否设置为未定义的值

$.getJSON("json.txt", function(myJsonData) {
         var elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW
         , arr = [];

         for (key in myJsonData) {

             /*---Some operations for giving values all the variables---*/

             //Getting image dimensions
             var tempImg = new Image();
             tempImg.onload = function() {
                 imgW = this.width;
                 imgH = this.height;
                 console.log(imgW + 'x' + imgH);
                 loaded += 1;
                 var dfd = new $.Deferred();
                 //Filling the new json
                 var newJsonData = {
                   "elemID": 'elemID_' + elemID,
                   "type": elemType,
                   "url": elemURL,
                   "thumbnail": thumb,
                   "menuItem": menuItem,
                   "date": date,
                   "W": imgW,
                   "H": imgH
                 };
                 arr.push(dfd.resolve(newJsonData))
             }
             tempImg.src = elemURL;

         };
         // $.when.apply($, arr).then(function() {
         //  do stuff with `newJsonData` objects
         //  console.log(arguments)
         // })
         return $.when.apply($, arr)
     })

尝试创建一个包含
newJsonData
的jQuery延迟对象数组,其中定义了
newJsonData
,并在
img
onload处理程序中解析延迟对象;从包含延迟对象数组的
$.getJSON()
返回新的承诺对象

注意,不确定在哪里

var elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW;
是否设置为未定义的值

$.getJSON("json.txt", function(myJsonData) {
         var elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW
         , arr = [];

         for (key in myJsonData) {

             /*---Some operations for giving values all the variables---*/

             //Getting image dimensions
             var tempImg = new Image();
             tempImg.onload = function() {
                 imgW = this.width;
                 imgH = this.height;
                 console.log(imgW + 'x' + imgH);
                 loaded += 1;
                 var dfd = new $.Deferred();
                 //Filling the new json
                 var newJsonData = {
                   "elemID": 'elemID_' + elemID,
                   "type": elemType,
                   "url": elemURL,
                   "thumbnail": thumb,
                   "menuItem": menuItem,
                   "date": date,
                   "W": imgW,
                   "H": imgH
                 };
                 arr.push(dfd.resolve(newJsonData))
             }
             tempImg.src = elemURL;

         };
         // $.when.apply($, arr).then(function() {
         //  do stuff with `newJsonData` objects
         //  console.log(arguments)
         // })
         return $.when.apply($, arr)
     })

下面是一些可能对您有所帮助的伪代码——我强烈建议使用库来实现这一点。我在我的示例中使用了
parallel
函数

var elems = document.querySelectorAll("img");
var fns = Array.prototype.map.call(elems, function(current){

/*
  get image dimensions here, using the "current" argument
  make sure to return a function that takes a callback (async expects this)
  the callback itself takes two args, first is the error object,
  the second will be the dimension data
*/
    current.onload = function() {
        var dimensionData = { w: current.width, h: current.height };
        return function(callback){
            callback(null, dimensionData);
        }
    }
});

/*
  fns will now be an array of functions that take a single callback
  async will process all of these functions in parallel and, 
  once they're all complete, will call its own callback. in your case,
  results will be an array of dimensional data for each of your images and, 
  now that you know they've all loaded, can safely write it to the JSON
*/

async.parallel(fns, function(err, results){
    writeToJson(JSONData);
});

我们将很快尝试用一个完整的示例来更新此内容。我现在有点忙。

这里有一些伪代码可能会对您有所帮助-我强烈建议使用库来实现这一点。我在我的示例中使用了
parallel
函数

var elems = document.querySelectorAll("img");
var fns = Array.prototype.map.call(elems, function(current){

/*
  get image dimensions here, using the "current" argument
  make sure to return a function that takes a callback (async expects this)
  the callback itself takes two args, first is the error object,
  the second will be the dimension data
*/
    current.onload = function() {
        var dimensionData = { w: current.width, h: current.height };
        return function(callback){
            callback(null, dimensionData);
        }
    }
});

/*
  fns will now be an array of functions that take a single callback
  async will process all of these functions in parallel and, 
  once they're all complete, will call its own callback. in your case,
  results will be an array of dimensional data for each of your images and, 
  now that you know they've all loaded, can safely write it to the JSON
*/

async.parallel(fns, function(err, results){
    writeToJson(JSONData);
});
我们将很快尝试用一个完整的示例来更新此内容。我现在有点忙。

您可以使用jQuery来完成这项工作:

$('<img/>', { src : elemURL }).promise().done(function(img) {
    //give some time to populate attributes to img
    setTimeout(function() {
       console.log(img[0].width, img[0].width);
    }, 200);     
})  
您可以使用jQuery来实现这一点:

$('<img/>', { src : elemURL }).promise().done(function(img) {
    //give some time to populate attributes to img
    setTimeout(function() {
       console.log(img[0].width, img[0].width);
    }, 200);     
})  

我不是百分之百确定你的问题,但也许这会有所帮助。 处理JSON文本,然后使用deferred来处理结果……可能需要一些定制,但应该给出一个示例

// makeClass - By Hubert Kauker (MIT Licensed)
// original by John Resig (MIT Licensed).
function makeClass() {
    var isInternal;
    return function (args) {
        if (this instanceof arguments.callee) {
            if (typeof this.init == "function") {
                this.init.apply(this, isInternal ? args : arguments);
            }
        } else {
            isInternal = true;
            var instance = new arguments.callee(arguments);
            isInternal = false;
            return instance;
        }
    };
}
var ImagesClass = makeClass();
ImagesClass.prototype.init = function (elemID, elemType, elemURL, thumb, menuItem, adate, imgW, imgH) {
    this.elemID = 'elemID_' + elemID;
    this.type = elemType;
    this.url = elemURL;
    this.thumbnail = thumb;
    this.menuItem = menuItem;
    this.date = adate;
    this.W = imgW;
    this.H = imgH;
    this.newJsonData = {
        "elemID": this.elemID,
            "type": this.type,
            "url": this.url,
            "thumbnail": this.thumbnail,
            "menuItem": this.menuItem,
            "date": this.date,
            "W": this.W,
            "H": this.H
    };
};

var myimages = [];
var dfd = new $.Deferred();
dfd.done(function (imagearray) {
    //do something to process the array of images here - they are loaded in imagearray
});

var jqxhr = $.getJSON("json.txt");
jqxhr.done(function (myJsonData) {
    // HUGE assumption on my part that each myJsonData in json.txt contains each of these with these name:
    //  elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW
    var obj = jQuery.parseJSON(myJsonData);

    jQuery.map(obj, function (n, i) {
        var myImageObj = ImagesClass(n.elemID, n.elemType, n.elemURL, n.thumb, n.date, n.menuItem, n.imgH, n.imgW);
        myimages.push(myImageObj.newJsonData);
        dfd.resolve(myimages);
    });

});
jqxhr.fail(function () {
    console.log("error");
});
jqxhr.always(function () {
    console.log("complete");
});

我不是百分之百确定你的问题,但也许这会有所帮助。 处理JSON文本,然后使用deferred来处理结果……可能需要一些定制,但应该给出一个示例

// makeClass - By Hubert Kauker (MIT Licensed)
// original by John Resig (MIT Licensed).
function makeClass() {
    var isInternal;
    return function (args) {
        if (this instanceof arguments.callee) {
            if (typeof this.init == "function") {
                this.init.apply(this, isInternal ? args : arguments);
            }
        } else {
            isInternal = true;
            var instance = new arguments.callee(arguments);
            isInternal = false;
            return instance;
        }
    };
}
var ImagesClass = makeClass();
ImagesClass.prototype.init = function (elemID, elemType, elemURL, thumb, menuItem, adate, imgW, imgH) {
    this.elemID = 'elemID_' + elemID;
    this.type = elemType;
    this.url = elemURL;
    this.thumbnail = thumb;
    this.menuItem = menuItem;
    this.date = adate;
    this.W = imgW;
    this.H = imgH;
    this.newJsonData = {
        "elemID": this.elemID,
            "type": this.type,
            "url": this.url,
            "thumbnail": this.thumbnail,
            "menuItem": this.menuItem,
            "date": this.date,
            "W": this.W,
            "H": this.H
    };
};

var myimages = [];
var dfd = new $.Deferred();
dfd.done(function (imagearray) {
    //do something to process the array of images here - they are loaded in imagearray
});

var jqxhr = $.getJSON("json.txt");
jqxhr.done(function (myJsonData) {
    // HUGE assumption on my part that each myJsonData in json.txt contains each of these with these name:
    //  elemID, elemType, elemURL, thumb, date, menuItem, imgH, imgW
    var obj = jQuery.parseJSON(myJsonData);

    jQuery.map(obj, function (n, i) {
        var myImageObj = ImagesClass(n.elemID, n.elemType, n.elemURL, n.thumb, n.date, n.menuItem, n.imgH, n.imgW);
        myimages.push(myImageObj.newJsonData);
        dfd.resolve(myimages);
    });

});
jqxhr.fail(function () {
    console.log("error");
});
jqxhr.always(function () {
    console.log("complete");
});

data
在哪里定义?您正在
循环中为..加载相同的图像。这是你想要的吗?试着用myJsonData来代替数据,比如for(key in myJsonData)@hindstrest-no,我有很多图像。我想得到所有这些的宽度和高度,并将其放入新的Json中。但我认为事情是异步发生的,因为当我console.log图像维度和新的json时,json首先被打印出来/@对不起,那是我的错。我现在修复了它。
data
在哪里定义?您正在
for..in
循环中加载相同的图像。这是你想要的吗?试着用myJsonData来代替数据,比如for(key in myJsonData)@hindstrest-no,我有很多图像。我想得到所有这些的宽度和高度,并将其放入新的Json中。但我认为事情是异步发生的,因为当我console.log图像维度和新的json时,json首先被打印出来/@对不起,那是我的错。我现在修好了。你找到解决方案了吗?你找到解决方案了吗?