[英]How to put async-await in a loop? Not working
我使用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);
}
})();
}
為此代碼生成的日志是:
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)
我希望這能在classifier.addImage
的函數回調中打印圖像的實際大小,而是獲得0x0紋理
設置image.src
后立即讀取image.height
image.src
導致0為高度。 設置src
您應該等待加載圖像。 沒有承諾await
加載圖像。 相反,它確實有一個名為onload
的回調:
let img = new Image();
img.onload = function() { console.log("Height: " + this.height); }
img.src = "...";
嘗試使用map函數而不是for循環,將nimgs轉換為數組並使用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 / await和forEach循環
有關更多信息,請參閱此文章: https : //lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795/
你的建議是宣布的不良做法。
“等待內部循環”不是一個好習慣。
理論上,你不能在循環的每次迭代中等待異步操作。 相反,您必須聲明所有異步操作,然后等待。
我認為ES Lint的這個例子填補了你的場景。
此規則的正確代碼示例:
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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.