多个异步回调javascript我该如何解决?

时间:2012-11-27 12:57:49

标签: javascript asynchronous callback

我陷入了纠结,可能涉及多个异步回调情况。

我有一个名为populatePageArea()的javascript函数

在populatePageArea中,它遍历这个类似于数组的变量,在其他代码中称为pages。

function populatePagesArea() {
  // there was some code before the for loop

  for (var i=0, l=pages.length; i<l; i++) {    
    addToPagesArea(pages[i], "");   
  }

  // some code after...
}

在addToPagesArea函数中,我使用HTML 5中的FileAPI来预览拖放文件和其他代码。

function addToPages(file, front) {
  // there was some code before..
  reader = new FileReader();
  reader.onload = (function (theDiv) {
    return function (evt) {
      var backgroundimage = "url(" + evt.target.result + ")";
  theDiv.css("background-image", backgroundimage);
      var sizeSettings = getSizeSettingsFromPage(file, calculateRatio);

};

  }(imageDiv));

  // step#3 execute file reader
  reader.readAsDataURL(file);
  // there was some code after..
}

所以每次我预览文件时,我都会尝试对文件的尺寸进行一些计算。

function getSizeSettingsFromPage(file, whenReady) {
    reader = new FileReader();
    reader.onload = function(evt) {
        var image = new Image();
        image.onload = function(evt) {
            var width = this.width;
            var height = this.height;
            var filename = file.name;
            if (whenReady) {
                whenReady(width, height, filename);
            }
        };
        image.src = evt.target.result; 
    };
    reader.readAsDataURL(file);

}
 function calculateRatio(width, height, filename) {

    var ratio = width/height;

    var object = new Object();
    object['height']    = width;
    object['width']     = height;
    object['ratio']     = ratio;
    object['size']      = 'Original';

    for (var size in SIZES) {
        var min = SIZES[size].ratio - 0.01;
        var max = SIZES[size].ratio + 0.01;

        if (ratio <= max && ratio >= min) {
            object['size'] = size;
        }
    }

    pageSizes.add(filename, object);

}
在calculateRatio中看到的

pageSizes 是一个全局变量,它是一个类似数组的变量类型。

在populatePagesArea被调用之前,它肯定是空的。

情况如下:

我的代码是:

populatePagesArea();
getMajorityPageSize(); // this acts on the supposedly non-empty pageSizes global variable

但是因为我认为没有在所有预览图像上调用calculateRatio,所以当调用getMajorityPageSize时,pageSizes总是空的。

如何确保在调用populatePagesArea之后,只有在所有pages都经过calculateRatio函数后才会触发getMajorityPageSize?

我相信这是异步回调。但我不知道如何为需要经历异步回调函数(如calculateRatio)的对象数组执行此操作。

1 个答案:

答案 0 :(得分:1)

简单的解决方案(我已使用// ***标记了我的更改:

// ***
var totalPages;

function populatePagesArea() {
  // there was some code before the for loop

  // ***
  totalPages = pages.length;
  for (var i=0, l=pages.length; i<l; i++) {    
    addToPagesArea(pages[i], "");   
  }

  // some code after...
}

function addToPages(file, front) {
    // there was some code before..
    reader = new FileReader();
    reader.onload = (function (theDiv) {
      return function (evt) {
        var backgroundimage = "url(" + evt.target.result + ")";
        theDiv.css("background-image", backgroundimage);
        var sizeSettings = getSizeSettingsFromPage(file, calculateRatio);
        // *** Check to see if we're done after every load
        checkPagesReady();
      };

    }(imageDiv));

    // step#3 execute file reader
    reader.readAsDataURL(file);
    // there was some code after..
}

// *** Call getMajorityPageSize() here, only after all pages have loaded.
function checkPagesReady() {
    if (pageSizes.length >= totalPages)
        getMajorityPageSize();
}

如果您稍后要处理更多异步事件,那么更好的解决方案是使用promises重构您的代码。 Promises是一种API,旨在以系统和有组织的方式处理异步编程。如果你要做更多的异步工作,它会让你的生活变得更轻松。有很多免费图书馆支持承诺,其中一个主要参与者是Q.js