gpt4 book ai didi

javascript - .then() 在循环中不多次执行内部函数

转载 作者:行者123 更新时间:2023-11-30 09:21:05 24 4
gpt4 key购买 nike

我正在编写一段实现 promise 的代码。它在一个循环内并迭代输入到页面中的图像数量。首先它应该用新图像更新 Canvas ,然后它应该运行一些代码从 Canvas 图像中获取信息。这是我当前的功能。

这是将图像更改为输入中的下一张图像的原因。

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);
})
var imgData = context.getImageData(0,0,canvas.width,canvas.height);
d.resolve(imgData);
};
FR.readAsDataURL(fileUpload.files[i]);
}
return d.promise();
}

这是在 .then() 命令中调用的另一个函数的片段。

function read_image (imgData) {
console.log("in read_image");
data = imgData.data;
/*doing some stuff to the data object*/
console.log("here is some data output");
}

最后是调用这两个函数的地方

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

所以发生的事情是 Canvas 正在用新图像更新,但只有当最终图像更新到 Canvas 时,我才会看到来自 read_image() 函数的任何 console.logs ,我只看到一个输出。这是控制台输出的示例。

loop:0
loop:1
loop:2
loop:3
loop:4
loop:5
loop:6
loop:8
in read_image
here is some data output

如能深入了解 then() 中的函数为何仅被调用一次,我们将不胜感激。

最佳答案

您需要使用letconstvard 声明为局部函数。您可能会覆盖更高范围的 d 然后解析错误的。

function readNextImage(i) {
var d = new $.Deferred();
//^^^

其他问题:

  1. FileReader 对象没有错误处理,因此任何错误都会导致您的 promise 永远不会解决或拒绝。
  2. 您无需等待 fabric.Image.fromURL()(这可能是异步的)完成后才 resolve 您的 promise。
  3. 如果您的 if 语句不满足 if (fileUpload.files && fileUpload.files[i]),那么您将永远不会解决或拒绝 promise 。

这是解决这四个问题的尝试(无法测试代码以确保其完全正确):

function readNextImage(i) {
var 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);
var imgData = context.getImageData(0, 0, canvas.width, canvas.height);
d.resolve(imgData);
});
};
FR.onerror = function(e) {
d.reject(e);
}
// start the file reader
FR.readAsDataURL(fileUpload.files[i]);
} else {
// not sure what you want to do here, but you need to resolve or reject the promise
d.resolve()
}
return d.promise();
}

当编写包含多个尚未处理 promise 的异步操作的代码时,通常最好在最低级别“promisify”每个异步操作。这样一来,您就可以使用 promise 的顺序和流程控制以及错误处理来一致地编写所有程序逻辑(这是一个很大的优势)。在这种情况下,您可以这样做:

function readFileDataURL(f) {
return new Promise(function(resolve, reject) {
var fr = new FileReader();
fr.onload = resolve;
fr.onerror = reject;
fr.readAsDataURL(f);
});
}

function imageFromURL(data) {
return new Promise(function(resolve, reject) {
fabric.Image.fromURL(data, resolve)
});
}

function readNextImage(i) {
if (fileUpload.files && fileUpload.files[i]) {
return readFileDataURL(fileUpload.files[i]).then(function(e) {
return imageFromURL(e.target.result);
}).then(function(img) {
img.set({
left: 0,
top: 0,
evented: false
});
img.scaleToWidth(canvas.width);
img.setCoords();
canvas.add(img);
var imgData = context.getImageData(0,0,canvas.width,canvas.height);
return imgData;
});
} else {
// nothing to do here
return Promise.resolve();
}
}

请注意,您还获得了两个实用函数,它们在您可能可以在其他地方重用的 promise 中起作用。

关于javascript - .then() 在循环中不多次执行内部函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51623081/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com