Javascript 如何将async Wait放入循环中?不起作用

Javascript 如何将async Wait放入循环中?不起作用,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我在一个机器学习项目中使用ml5对图像进行分类。该程序从json文件中获取图像路径和类型,然后将每个图像添加到ml5分类器,然后用于训练机器学习模型 当我尝试只将一个图像加载到分类器中时,它工作正常(但是它不会创建模型,因为训练至少需要2个)。但是,当我尝试在for循环中将这些图像添加到分类器时,它会给我带来错误 文件由按钮触发的load_data()功能加载load_data()调用load_imgs(label,nimgs)其中label是文件夹,nimgs是其中的图像数load_imgs(

我在一个机器学习项目中使用ml5对图像进行分类。该程序从json文件中获取图像路径和类型,然后将每个图像添加到ml5分类器,然后用于训练机器学习模型

当我尝试只将一个图像加载到分类器中时,它工作正常(但是它不会创建模型,因为训练至少需要2个)。但是,当我尝试在for循环中将这些图像添加到分类器时,它会给我带来错误

文件由按钮触发的
load_data()
功能加载
load_data()
调用
load_imgs(label,nimgs)
其中label是文件夹,nimgs是其中的图像数
load_imgs(label,nimgs)
然后在nimgs上循环,获取数据(json文件)中指定的图像路径,从中生成图像元素,然后将其添加到分类器中

这些功能定义为:

    async function load_imgs(label, nimgs) {

        const forLoop = async _ => {
            for (let i = 0; i < nimgs; i++) {
                const imageData = await data.children[label].children[i]
                const image = document.createElement("img")
                image.src = imageData.path
                const type = await imageData.type;
                await classifier.addImage(image, type, (res) => {
                    console.log("image added to classifier", image.height);
                    console.log(image);

                })

            }
        }
        await forLoop()
    }

    function load_data() {
        (async() => {
            try {
                await load_imgs(0, googleImages);
                await load_imgs(1, amazonImages);
                await load_imgs(2, paypalImages);
                await load_imgs(3, facebookImages);
                await load_imgs(4, dropboxImages);
                console.log("images added");

            } catch (error) {
                console.log(error);
            }
        })();

    }
异步函数加载\u imgs(标签,nimgs){ 常量forLoop=async\ux=>{ for(设i=0;i{ console.log(“图像添加到分类器”,图像.height); console.log(图像); }) } } 等待forLoop() } 函数加载_数据(){ (异步()=>{ 试一试{ 等待加载(0,谷歌图片); 等待加载图像(1,亚马逊图像); 等待加载图片(2张,付费图片); 等待加载图片(3张,facebook图片); 等待加载IMG(4个dropboxImages); 控制台日志(“添加图像”); }捕获(错误){ console.log(错误); } })(); } 为此代码生成的日志为:

    index-train.html:106 Live reload enabled.
    train.js:84 json loaded
    train.js:69 Model loaded
    train.js:38 image added to classifier 0
    train.js:39 <img src=​"all_data/​google/​google_85.png">​
    train.js:107 Error: Requested texture size [0x0] is invalid.
        at re (tf-core.esm.js:17)
        at Wi (tf-core.esm.js:17)
        at Gi (tf-core.esm.js:17)
        at t.createUnsignedBytesMatrixTexture (tf-core.esm.js:17)
        at t.acquireTexture (tf-core.esm.js:17)
        at t.acquireTexture (tf-core.esm.js:17)
        at t.uploadToGPU (tf-core.esm.js:17)
        at t.getTexture (tf-core.esm.js:17)
        at t.fromPixels (tf-core.esm.js:17)
        at t.fromPixels (tf-core.esm.js:17)
index train.html:106已启用实时重新加载。
train.js:84 json加载
列车.js:69型装载
train.js:38图像添加到分类器0
火车站:39​
train.js:107错误:请求的纹理大小[0x0]无效。
在re(tf core.esm.js:17)
在Wi(tf core.esm.js:17)
在Gi(tf core.esm.js:17)
在t.createUnsignedBytesMatrixture(tf core.esm.js:17)
在t.acquireTexture(tf core.esm.js:17)
在t.acquireTexture(tf core.esm.js:17)
在t.uploadToGPU(tfcore.esm.js:17)
at t.getTexture(tfcore.esm.js:17)
t.fromPixels(tf core.esm.js:17)
t.fromPixels(tf core.esm.js:17)

我希望这会在
分类器的函数回调中打印图像的实际大小。addImage
,但相反,它会在设置
图像后立即读取
图像。height
。src
会将0作为高度。设置
src
后,应等待图像加载。没有承诺等待加载图像。相反,它有一个名为
onload
的回调:

let img = new Image();
img.onload = function() { console.log("Height: " + this.height); }
img.src = "...";

尝试使用map函数而不是for循环,将nimgs转换为array并使用如下map函数:

async function load_imgs(label, nimgs) {

    await Promise.all(nimgs.map(async (i) => {
        const imageData = await data.children[label].children[i]
        const image = document.createElement("img")
        image.src = imageData.path
        const type = await imageData.type;
        await classifier.addImage(image, type, (res) => {
                console.log("image added to classifier", image.height);
                console.log(image);

        })
    }))
}
请参见以下说明:


有关更多信息,请参阅本文:

您所建议的是一种公开的不良做法

“将等待放入循环中”不是一个好做法

理论是,在循环的每次迭代中,都不能等待异步操作。相反,您必须声明所有异步操作,然后等待。

我认为这个例子符合你的情况

此规则的正确代码示例:

async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Good: all asynchronous operations are immediately started.
    results.push(bar(thing));
  }
  // Now that all the asynchronous operations are running, here we wait until they all complete.
  return baz(await Promise.all(results));
}
async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Bad: each loop iteration is delayed until the entire asynchronous operation completes
    results.push(await bar(thing));
  }
  return baz(results);
}
此规则的错误代码示例:

async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Good: all asynchronous operations are immediately started.
    results.push(bar(thing));
  }
  // Now that all the asynchronous operations are running, here we wait until they all complete.
  return baz(await Promise.all(results));
}
async function foo(things) {
  const results = [];
  for (const thing of things) {
    // Bad: each loop iteration is delayed until the entire asynchronous operation completes
    results.push(await bar(thing));
  }
  return baz(results);
}

wait data.children[label].children[i]
data是加载到对象中的json。
标签
表示在json中定义顺序的文件夹索引
i
表示包含图像文件的本地路径的字符串添加
image.onload
侦听器。
image.src=imageData.path
并不表示图像已加载。可以help@lx1412谢谢你这一切就像是我手指上的一根刺。非常感谢
image。onload
成功了,不过,谢谢,我也要试试这个