[英]Using for..in loop with Promises and asynchronous functions
我需要能够遍历图像的一个对象,并且一次对每个图像执行一个异步功能。 如果将图像对象转换为数组,则可以正常工作,但是我想使用for...in
循环来执行此操作,因此也可以使用图像键。 我还需要能够像现在这样在最后执行操作。
var images = {
ABD: '1464685684713583388647.jpg',
ABY: '1457524543088191607099.jpg',
ADV: '1478877365443818880647.jpg',
AFD: '1457527861824290195088.jpg',
}
var imagesArray = Object.values(images);
var len = imagesArray.length;
function asynchronousImageFunction (key, image, onSuccess, onFail) {
setTimeout(function () {
console.log(key);
console.log(image);
onSuccess();
}, Math.random() * 1000)
}
(function loop(i) {
if (i < len) {
new Promise(function (resolve, reject) {
asynchronousImageFunction ('key', imagesArray[i], resolve, reject);
}).then(loop.bind(null, i+1));
} else {
console.log('end');
}
})(0);
顺序并不重要,但是让它们一个接一个地调用是很重要的,并且还需要进行onComplete或结束调用。 我只是无法理解,有人可以帮忙吗?
使用reduce
是一种很好的方法。 您可以将键/值对与Object.entries
一起传递
var images = { ABD: '1464685684713583388647.jpg', ABY: '1457524543088191607099.jpg', ADV: '1478877365443818880647.jpg', AFD: '1457527861824290195088.jpg', } function asynchronousImageFunction(key, image, onSuccess, onFail) { setTimeout(function() { console.log(key); console.log(image); onSuccess(); }, 1000) } Object.entries(images).reduce((a, [key, value]) => { return a.then(() => new Promise((resolve, reject) => { asynchronousImageFunction(key, value, resolve, reject); }))}, Promise.resolve()) .then(() => console.log("end"))
另一方面,如果您的异步函数返回了自己的诺言,那么这看起来会容易一些:
var images = { ABD: '1464685684713583388647.jpg', ABY: '1457524543088191607099.jpg', ADV: '1478877365443818880647.jpg', AFD: '1457527861824290195088.jpg', } function asynchronousImageFunction(key, image, onSuccess, onFail) { return new Promise((resolve, reject) => { setTimeout(function() { console.log(key); console.log(image); resolve(); }, 1000) }) } Object.entries(images).reduce((a, [key, value]) => a.then(() => asynchronousImageFunction(key, value)) , Promise.resolve()) .then(() => console.log("end"))
如果还需要访问键,则只需使用Object.keys
或Object.entries
而不是Object.values
。
var imageKeysArray = Object.key(images);
var len = imagesArray.length;
(function loop(i) {
if (i < len) {
var key = imageKeysArray[i];
var value = images[key];
asynchronousImageFunction(key, value).then(loop.bind(null, i+1));
} else {
console.log('end');
}
})(0);
请注意, new Promise
包装器应直接在setTimeout
调用周围,位于asynchronousImageFunction
setTimeout
内部; 这使它更易于使用,并且您需要传递的回调更少。
让您将real for … in
循环的替代方法是async
/ await
语法:
(async function loop() {
for (const key in images)
await asynchronousImageFunction(key, images[key]);
console.log("end");
})();
实际上,您将无法使用for...in
来进行此操作。 不能指示for...in
和for...of
类for...in
循环在开始下一次迭代之前要等待异步事件。
您所要做的是实现一些行为,该行为的行为类似于所需的循环,但确实要等待异步事件。 您所做的工作就像一个数组的for...of
。 您可以通过执行Mark_M描述的操作来使键可用。
但是,这是一个非常常见的操作,并且已在async之类的库中进行了抽象(以及许多其他异步操作),使您可以跳过此烦恼并仅编写所需内容:
var images = {
ABD: '1464685684713583388647.jpg',
ABY: '1457524543088191607099.jpg',
ADV: '1478877365443818880647.jpg',
AFD: '1457527861824290195088.jpg',
}
function asynchronousImageFunction(key, image, callback) {
setTimeout(function () {
console.log(key);
console.log(image);
// Usual convention of `async` callbacks. The first argument should be
// null/undefined/omitted if no error occurred:
callback();
// If there was an error, you would instead do this:
// callback(err);
}, Math.random() * 1000)
}
async.eachOfSeries(images, function(image, key, callback) {
asynchronousImageFunction(key, image, callback);
}, function(err) {
console.log('end');
});
可以在这里找到async.eachOfSeries的文档。
您会发现我在这里没有使用Promise。 这主要是因为您的asynchronousImageFunction
功能以及async
库本身都是基于回调的。 在处理异步代码时,我的建议是尽量不要在样式之间来回切换,否则东西会令人困惑。
如果您能够使CommonJS模块在您的环境中工作,那么可以使用基于承诺的async
变体。 我的最爱之一在这里 。 有了它,您可以使循环本身基于承诺:
const pasync = require('pasync');
var images = {
ABD: '1464685684713583388647.jpg',
ABY: '1457524543088191607099.jpg',
ADV: '1478877365443818880647.jpg',
AFD: '1457527861824290195088.jpg',
}
function asynchronousImageFunction(key, image) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(key);
console.log(image);
resolve();
}, Math.random() * 1000);
});
}
pasync.eachOfSeries(
images,
(image, key) => asynchronousImageFunction(key, image)
)
.then(() => {
console.log('end');
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.