我需要调整一些图像的大小。问题是我使用的库每回调一次调整大小。
我想调整几张图片的大小,所以我把它放在一个循环中:
exports.resizeImages = function (req, res) {
var images = fs.readdirSync('uploads/');
for (var n = 0; n < files.length; n++) {
var tgt = 'uploads/resized/' + images[n];
gm(tgt).resize(150).write(tgt, function (err) {
if (err) {
console.log('resizing failed');
res.status(400).send('failed to resize');
return;
}
if (n == images.length) {
res.status(200).send();
}
});
}
}
我知道我不能这样做。我需要让循环等待,直到回调以某种方式响应。我已经看过一些例子,但我无法让它发挥作用。
有什么想法吗?
答案 0 :(得分:1)
您也可以使用node async模块
这样的事情:
var async = require('async');
exports.resizeImages = function (req, res) {
var images = fs.readdirSync('uploads/');
async.each(images, function(file, callback) {
var tgt = 'uploads/resized/' + file;
gm(tgt).resize(150).write(tgt, callback);
}, function(err) {
if(err) {
console.log('resizing failed');
return res.status(400).send('failed to resize');
} else {
//no error
return res.status(200).send();
}
});
}
答案 1 :(得分:0)
您需要使用promises编写for循环。选择你最喜欢的诺言库。详细信息包含在this question或this question中。或者在此blog post:
var Promise = require('bluebird');
var promiseWhile = function(condition, action) {
var resolver = Promise.defer();
var loop = function() {
if (!condition()) return resolver.resolve();
return Promise.cast(action())
.then(loop)
.catch(resolver.reject);
};
process.nextTick(loop);
return resolver.promise;
};
答案 2 :(得分:0)
如果你想保持裸露,可以使用外部计数器:
var images = fs.readdirSync('uploads/');
var processed = 0;
for (var n = 0; n < files.length; n++) {
var tgt = 'uploads/resized/' + images[n];
gm(tgt).resize(150).write(tgt, function (err) {
if (err) {
console.log('resizing failed');
res.status(400).send('failed to resize');
return;
}
processed++;
if (processed == images.length) {
res.status(200).send();
}
});
}
假设您只发送200 OK
所有图像都已正确调整大小。
答案 3 :(得分:0)
就像其他人提到的那样你可以使用promises,但是如果你不想在你的项目中开始使用promises async.js就完全适合这种事情了。
您的代码使用async.js重写:
exports.resizeImages = function (req, res) {
async.waterfall([
function readImages_step(done) {
readdir('uploads/', done);
},
function uploadImages_step(images, done) {
async.each(images, function(image, cb) {
var target = 'uploads/resized/' + image;
gm(target).resize(150).write(target, cb);
}, done);
}
], function (err) {
if (err) {
console.log('resizing failed');
return res.status(400).send('failed to resize');
}
return res.status(200).send();
}
};
我将readdirsync调用更改为异步。 Async.each将并行运行每个上传。