Javascript Node.js下载文件-并非所有请求都会解决,Promise.all不会触发

Javascript Node.js下载文件-并非所有请求都会解决,Promise.all不会触发,javascript,node.js,amazon-s3,request,Javascript,Node.js,Amazon S3,Request,我正在尝试使用request、fs extra在Node.js中编写一个程序,并承诺下载AmazonS3上提供的一系列文件 对于较小的文件,该程序可以工作。但是对于五个或更多较大的文件,至少有一个文件没有下载,因此Promise.all永远不会启动,因此没有控制台。log'Promise Finished:',value 目前,它下载的文件大部分是完整的,但最后一个或两个文件是部分的。没有错误进入控制台 我想知道是否有太多的请求同时发生,这就是为什么相同的文件无法下载?如果是这样的话,我该如何应

我正在尝试使用request、fs extra在Node.js中编写一个程序,并承诺下载AmazonS3上提供的一系列文件

对于较小的文件,该程序可以工作。但是对于五个或更多较大的文件,至少有一个文件没有下载,因此Promise.all永远不会启动,因此没有控制台。log'Promise Finished:',value

目前,它下载的文件大部分是完整的,但最后一个或两个文件是部分的。没有错误进入控制台

我想知道是否有太多的请求同时发生,这就是为什么相同的文件无法下载?如果是这样的话,我该如何应对

我期望的结果是完全下载每个文件并启动Promise.all,并且能够捕获正在发生的任何错误。此外,它需要在坏连接上执行

更新:在GitHub上发现此问题,这可能解释了为什么在我的场景中没有触发错误

您必须相应地使用reject


如其他答复所述;你必须拒绝。但当您拒绝时,这意味着任何成功的请求都将丢失,这取决于您如何继续您的过程

您可能不需要这样做,而是可以使用一个特殊值进行解析,以便确定如何处理成功和失败的请求:

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));
    }
  }
);

看起来我遇到的是这个bug的症状:

r.pipefs.createWriteStream'files/'+url中的r来自哪里?如果url.length如您所示仅为6,那么并行运行也不会太多。在文件系统中使用url作为文件名可能存在问题。此外,您在很多地方都缺少错误处理,例如在r.pipe上,因此如果您在那里遇到错误,您将永远无法解决或拒绝您的承诺。如果其中一些文件没有完成,那么某个地方就有错误,您只需确保您记录了所有可能的错误,然后他们可能会告诉您出了什么问题。您正在使用的任何基础结构代码都不会自动吞咽错误,因此您只需确保正在侦听并记录所有可能的错误。谢谢@jfriend00。我已经更新了问题中的代码,以侦听管道上的错误,并将查找其他位置来记录错误。在进行更多测试后,看起来我可能面临网络问题。我在另一个网络接口有线Thunderbolt连接上尝试了该代码,相同的代码从未失败。我仍然需要找到一个错误点来处理错误,所以我将继续努力。我已经在我的代码中添加了您的建议。虽然它不能解决我遇到的问题,也不能显示任何错误以提供洞察力,但我同意它改进了代码。您需要使用request.get来获取响应事件。所以,没有任何事件,承诺也从未得到解决。这是一个很棒的建议,我可能会使用它。我只是尝试实现这个,结果是一样的——仍然没有错误。你能看到我没有拒绝的其他地方吗?@MikeJenkins尝试代码2 URL并在你的问题中发布输出。我看不出代码有任何问题,但不确定您当前使用的代码是什么。如果Promise.all失败,您还应该记录错误:Promise.all.then.catcherr=>console.warn出错:,err。在Promise.all之后,有一个IFER应该抛出错误,因为err未定义,请删除该if语句。
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)
    });
  });
});
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));
    }
  }
);