承诺不强制顺序执行

时间:2018-07-31 18:39:31

标签: javascript jquery canvas promise

我正在尝试编写一个程序,将图像加载到画布中,然后在加载后从其中读取图像数据。这是执行不同操作的两个函数。

此功能读取文件输入数组中的下一张图像

function readNextImage(i) {
d = new $.Deferred();
if (fileUpload.files && fileUpload.files[i]) {
var FR = new FileReader();
FR.onload = function(e) {
  fabric.Image.fromURL(e.target.result, function(img) {
    img.set({
      left: 0,
      top: 0,
      evented: false
    });
    img.scaleToWidth(canvas.width);
    img.setCoords();
    canvas.add(img);
  })
};
FR.readAsDataURL(fileUpload.files[i]);
}
d.resolve();
return d.promise();
}

这实际上是解析图像数据以从中提取信息

function read_image () {
d = new $.Deferred();
imgData = context.getImageData(0,0,canvas.width,canvas.height);
data = imgData.data;
var value_min=100;
var value_max=0;
var total_light=0;
var total_shadow=0;
for (var j=0; j<boundary.length; j+=1) {
        var hsv = rgb2hsv(data[boundary[j]], data[boundary[j]+1], data[boundary[j]+2]);
        if(hsv.v < value_min){
            value_min = hsv.v;
        }
        if(hsv.v > value_max){
            value_max = hsv.v;
        }
}

var value_median = (value_min + value_max)/2;

for (var j=0; j<boundary.length; j+=1) {
    var hsv = rgb2hsv(data[boundary[j]], data[boundary[j]+1], data[boundary[j]+2]);
    if(hsv.v < value_median){
        //console.log("this value:"+hsv.v);
        total_shadow+=1;
    } else {
        total_light+=1;
    }
}       

var total_interception = total_shadow/boundary.length;
console.log("interception:" + total_interception);
total_interception = total_interception * 100;
total_interception = total_interception.toPrecision(4);
document.getElementById("interception").innerHTML=total_interception.toString()+"%";

d.resolve();
return d.promise();
}

最后是调用两个函数的代码

for (var image_num=0; image_num<fileUpload.files.length; image_num+=1){
    promise = readNextImage(image_num).then(read_image);
}

我阅读了有关promise的信息,因为它是异步执行的,我想在执行任何其他操作之前强制其将图像加载到画布中。当前,该程序执行read_image()函数的次数与文件输入中存在图像的次数相同,然后执行该操作之后,它将依次向画布加载图像。因此,现在只从加载的第一张图像中获取数据。

1 个答案:

答案 0 :(得分:2)

ReadNextImage()中,您要在返回承诺之前立即对其进行解析,这实际上会将其转换回一个普通的旧同步函数:无需等待就可以解析承诺。

代替在FR.onload回调中解析promise;这样,它会一直等到图像数据加载完毕后,再触发Promise的then()

readImage()函数似乎根本不需要异步;您只需从该函数中删除与承诺相关的代码即可。

也-我对这里的上下文或画布代码的用途尚不完全清楚,但我怀疑这不是让两个函数都从似乎是同一画布的对象中读取并读取它们,而是当循环中有多个文件时,将导致冲突,您可能希望第一个函数异步检索其数据,然后将其显式传递给第二个同步函数:

function readNextImage(i) {
  d = new $.Deferred();
  if (fileUpload.files && fileUpload.files[i]) {
    var FR = new FileReader();
    FR.onload = function(e) {
      // ... etc to build up the `img` var...
      d.resolve(img); // <-- here, and pass the data along
    };
    FR.readAsDataURL(fileUpload.files[i]);
  }
  // d.resolve() <-- not here
  return d.promise();
}

function read_image(imgData) {
  // Do stuff™ to `imgData` (synchronously) from the param, rather than reading from the canvas
}

for (var image_num=0; image_num<fileUpload.files.length; image_num+=1){
  readNextImage(image_num).then(read_image);
}