【问题标题】:Promises not forcing sequential executionPromise 不强制顺序执行
【发布时间】:2018-08-01 03:15:15
【问题描述】:

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

该函数读取文件输入数组中的下一张图片

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() 函数的次数与文件输入中的图像一样多,然后在执行此操作之后,它会按顺序加载带有图像的画布。所以现在它只从加载的第一张图片中获取数据。

【问题讨论】:

  • read_image 是同步的,它不应该返回一个承诺。

标签: javascript jquery canvas promise


【解决方案1】:

ReadNextImage() 中,您在返回它之前立即解决了promise,这实际上将它变成了一个普通的旧同步函数:promise 无需等待任何东西即可解决。

而是在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);
}

【讨论】:

  • 好了这样就解决了多次读取同一张图片的问题,现在只执行了一次read_image()函数
  • 我承认不完全理解你正在做的图像处理,但我已经扩展了答案以展示如何通过解析回调而不是依赖于 @987654326 的当前状态来传递数据@.
  • jquery.js:3860 jQuery.Deferred exception: Cannot read property '280108' of undefined TypeError: Cannot read property 'data' of undefined at read_image line 263 位于代码 data = imgData.data; 的这一行,看起来它在传递它时不知道如何处理它。有什么想法吗?
  • img 可能不是您要传递的变量,这是您的代码中我不清楚的部分——但想法是 d.resolve(foo) 将传递 foo 为Promise 的 then() 的第一个参数,或者在本例中是您的 read_image 函数。
  • 好的,非常感谢您的帮助。我看看能不能从这里弄明白!
猜你喜欢
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 2018-07-21
  • 2016-08-07
  • 2020-03-13
  • 2022-01-02
  • 2010-12-23
相关资源
最近更新 更多