我正在遍历许多图像 uri 以将它们下载到本地。
这是我正在使用的代码:
const optionsImg = {
url: basePath,
headers: {
'User-Agent': 'request'
}
};
let download = function(url, filename, callback) {
optionsImg.url = url
request.head(optionsImg, (err, res, body) => {
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(optionsImg).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
但它只会保存列表中的最后一张图片。我怀疑正在发生的是它正在尝试下载异步,并且 fs.createWriteStream 一直被中断,直到列表完成。因此只能成功下载最后一张图片。
console.logs 确实显示不同的内容长度。
如何最好地解决这个问题?提前致谢。
编辑: 这是循环代码:
for (let x = 0; x < pics.length; x++) {
download(pics[x], localPath + x + '.jpeg', function() {
console.log('done');
});
}
答案 0 :(得分:2)
到 request.head
完成时——因为它是一个网络请求,就计算机而言它也可能是“永恒”——将始终具有相同的值因为你不断重复使用同一个对象。
考虑一下:
optionsImg.url
您可以通过克隆对象来解决上述问题:
const obj = { a: undefined };
for(let i = 0; i <= 3; i++) {
obj.a = i;
setTimeout(console.log, 100, obj);
}
// will log {a:3} always
有些适用于您的代码:
const obj = { a: undefined };
for(let i = 0; i <= 3; i++) {
const obj2 = Object.assign({}, obj);
obj2.a = i;
// or const obj2 = { ...obj, a: i };
setTimeout(console.log, 100, obj2);
}
// will log {a:0}, {a:1}, {a:2}, {a:3}
let download = function(url, filename, callback) {
const options = {
...optionsImg,
url: url,
}
/* alternatively you can do:
const options = Object.assign({}, optionsImg);
options.url = url; */
request.head(options, (err, res, body) => {
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(options).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
和 Object.assign
做一个浅拷贝,所以 {...optionsImg}
仍然会被重用。
现在每次调用 headers
并且它触发的 download()
调用都将拥有选项对象的“自己的”副本。
编辑:对于 OP 中所述的问题,您不需要这个,但如果您还想复制标头对象 - 也许您想为每个请求操作其值 - 那么您可以这样做:
request()
您还可以搜索递归对象克隆实用程序;有很多。