我尝试使用request,fs-extra尝试在Node.js中编写程序,并承诺下载在Amazon S3上提供的文件数组。
使用较小的文件,程序可以正常工作。但是有五个或更多大文件,至少有一个文件没有下载,因此Promise.all永远不会触发,所以没有console.log(' Promise Finished:',value) ;
目前它下载了大部分文件(完整),但最后一个或两个文件是部分文件。没有错误进入控制台。
var urls = ['http://www.amazons3.com/10mb.mp4',
'http://www.amazons3.com/20mb.mp4', 'http://www.amazons3.com/15mb.mp4', 'http://www.amazons3.com/19mb.mp4', 'http://www.amazons3.com/18mb.mp4', , 'http://www.amazons3.com/20mb.mp4'];
var promises = urls.map(url => {
return new Promise((resolve, reject) => {
var r = request(url)
.on('response', (resp) => {
if (resp.statusCode === 200) {
console.log('Started: ', url);
r.pipe(fs.createWriteStream('files/' + fileName))
.on('error', function(err) {
console.log(err)
reject(err)
})
.on('finish', function () {
console.log('Downloaded: ', url);
resolve(url);
});
} else {
console.log(`${resp.statusCode} error for`, url);
reject(`${resp.statusCode} error for ${url}`)
}
}).on('error', function(err) {
console.log(err)
reject(err)
});
});
});
Promise.all(promises).then(function(values){
if (err) return console.error(err);
console.log('Promise Finished: ', values);
});
我想知道是否有太多请求同时发生,这就是为什么同样的文件无法下载?如果是这样,我该如何解决这个问题?
我希望的结果是完全下载每个文件并激活Promise.all并能够捕获正在发生的任何错误。此外,它需要在不良连接上表现出色。
更新:在GitHub上发现此问题,这可以解释为什么错误在我的方案中没有触发。 https://github.com/request/request/issues/2161
答案 0 :(得分:1)
您必须相应地使用
reject
var promises = urls.map(url => {
return new Promise((resolve, reject) => {
var r = request.get(url)
.on('response', (resp) => {
if (resp.statusCode === 200) {
console.log('Started: ', url);
r.pipe(fs.createWriteStream('files/' + url))
.on('error', function(err) {
console.log(err)
reject(err)
})
.on('finish', function () {
console.log('Downloaded: ', url);
resolve(url);
});
} else {
console.log(`${resp.statusCode} error for`, url);
reject(`${resp.statusCode} error for ${url}`)
}
}).on('error', function(err) {
console.log(err)
reject(err)
});
});
});
答案 1 :(得分:0)
As stated in other answer; you have to reject. But when you reject that means that any request that succeeded is lost (depending on how you continue your process).
You may not want this and can instead resolve with a special value so you can figure out what to do with the succeeded and failed requests:
function Fail(reason){this.reason=reason;};
const isFail = x=>(x&&x.constructor)===Fail;
const isNotFail = x=>!isFail(x);
var promises = urls.map(url => {
return new Promise((resolve, reject) => {
//same as Akash
})
.catch(err=>new Fail([err,url]));
});
Promise.all(promises)
.then(
results=>{
const successes = results.filter(isNotFail);
const failed = results.filter(isFail);
if(failed.length!==0){
console.log("Some url(s) failed:");
console.log(failed.map(([err,url])=>url));
console.log("Errors:");
console.log(failed.map(([err,url])=>err));
}
}
);
答案 2 :(得分:0)
看起来我遇到的是这个错误的症状:https://github.com/request/request/issues/2161