imgObj將被加載時是否可以暫停.map()迭代?
不是,所以您使用異步循環。這裏有一個例子,看評論:
// A named IIFE
(function iteration(keys, index) {
// Get info for this iteration
let name = keys[index];
let img = gameConfig.playerElems[name];
let imgObj = new Image();
// Set event callbacks BEFORE setting src
imgObj.onload =() => {
playerElemsCounter++;
drawPlayer(imgObj);
next();
};
imgObj.onerror = next;
// Now set src
imgObj.src = img;
// Handles triggering the next iteration on load or error
function next() {
++index;
if (index < keys.length) {
iteration(keys, index);
}
}
})(Object.keys(gameConfig.playerElems), 0);
但,作爲Haroldo_OK指出,這將等待一個圖像請求下一個,這不僅沒有必要,而且有害之前加載。相反,請求全部,在您收到它們時繪製它們,然後繼續。你可能做到這一點的給自己的加載函數返回一個承諾:
const loadImage = src => new Promise((resolve, reject) => {
const imgObj = new Image();
// Set event callbacks BEFORE setting src
imgObj.onload =() => { resolve(imgObj); };
imgObj.onerror = reject;
// Now set src
imgObj.src = src;
});
然後:
// Load in parallel, draw as we receive them
Promise.all(Object.keys(gameConfig.playerElems).map(
key => loadImage(gameConfig.playerElems[key])
.then(drawPlayer)
.catch(() => drawPlayer(/*...placeholder image URL...*/))
)
.then(() => {
// All done, if you want to do something here
});
// No need for `.catch`, we handled errors inline
如果想(出於某種原因)撐起加載下一個圖像,同時等待以前認爲,loadImage
功能可以用不同的方式做到這一點,例如經典承諾reduce
模式:
// Sequential (probably not a good idea)
Object.keys(gameConfig.playerElems).reduce(
(p, key) => p.then(() =>
loadImage(gameConfig.playerElems[key])
.then(drawPlayer)
.catch(() => drawPlayer(/*...placeholder image URL...*/))
)
,
Promise.resolve()
)
.then(() => {
// All done, if you want to do something here
});
// No need for `.catch`, we handled errors inline
...或ES2017 async
/await
:
// Sequential (probably not a good idea)
(async function() {
for (const key of Object.keys(gameConfig.playerElems)) {
try {
const imgObj = await loadImage(gameConfig.playerElems[name]);
playerElemsCounter++;
drawPlayer(imgObj);
} catch (err) {
// use placeholder
drawPlayer(/*...placeholder image URL...*/);
}
}
})().then(() => {
// All done
});
// No need for `.catch`, we handled errors inline
邊注:有沒有必要使用map
如果你不是A) 從回調返回一個值,用於填充新數組map
創建,B) 使用數組map
返回。當你不這樣做時,只需使用forEach
(或for
或for-of
循環)。
你不能。你可以使用遞歸來實現這個 – Rajesh
這是不可能的,因爲即使圖像被加載,JS在事件循環返回之前也不會觸發事件。您將不得不以異步方式重新設計您的代碼。 –
通過一些小的調整,這個問題中解決方案的ES6部分也可以工作:[在所有異步forEach回調完成後回調](https://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach - 完成) – Andreas