简体   繁体   English

暂停 for 循环直到 function 完成

[英]Pause a for loop until function is completed

I've been scratching my brain at this a majority of the day, I am attempting to download multiple files that have iterating ID's, I use a for loop to iterate and call a web request that calls a function that downloads a file.我一天中的大部分时间都在绞尽脑汁,我试图下载多个具有迭代 ID 的文件,我使用 for 循环迭代并调用 web 请求,该请求调用 function 下载文件。

However, I noticed files tend to get corrupted due to multiple files being requested at once, I am using the following NPM Package https://www.npmjs.com/package/nodejs-file-downloader it has alot of neat features and its also promise based.但是,我注意到由于一次请求多个文件,文件往往会损坏,我正在使用以下 NPM Package https://www.npmjs.com/package/nodejs-file-downloader它有很多简洁的功能和它的也基于 promise。

My problem is I don't know how to use promises with the package, I would like for the loop to wait until the downloadFile() that the file was succesfully downloaded.我的问题是我不知道如何使用 package 的承诺,我希望循环等到文件下载成功的 downloadFile()。

const axios = require('axios');
const url = require('url')
const fs = require('fs');
const DOWNLOAD_DIR = '/'
var downloadCo5mplete = false
const Downloader = require("nodejs-file-downloader");
const sleep = require('sleep-promise');

async function getFile(version)
{

  axios.request({
    url: "https://****.****.com/v1/id/*****/version/" + version,
    method: "get",
    headers:{
        ContentType: 'application/json',
        Accept: "application/json",
        Cookie: ""
    } 
  }).then(function (response) {
      const placeData = response.data.location;
      //if placeData is null, then the version is not available
      if(placeData == null)
      {
        console.log("Version " + version + " not available");
        return;
      }
      console.log("Version " + version + " available");

      downloadFile(version, placeData)
      

  }).catch(function (error) {
      //console.log(error);
  });

}



async function downloadFile(version, data)
{
  const downloader = new Downloader({
    url: data, //If the file name already exists, a new file with the name 200MB1.zip is created.
    directory: "./2506647097", //This folder will be created, if it doesn't exist.
    fileName: "2506647097 - " + version + ".rbxl",
    onError: function (error) {
      //You can also hook into each failed attempt.
      console.log("Error from attempt ", error);
    },
  });
  
  try {
    downloader.download(); //Downloader.download() returns a promise.
    console.log("Downloaded version " + version + " successfully");
  } catch (error) {
    //IMPORTANT: Handle a possible error. An error is thrown in case of network errors, or status codes of 400 and above.
    //Note that if the maxAttempts is set to higher than 1, the error is thrown only if all attempts fail.
    console.log("Download failed", error);
  }
};


async function main()
{
  for(var i = 7990; i < 7995; i++)
  {
    await getFile(i);
  }
}

main()

Currently my console looks like this upon running the code.目前我的控制台在运行代码时看起来像这样。

Version 7990 available
Version 7991 available
Version 7992 available
Downloaded version 7990 successfully
Version 7993 available
Downloaded version 7991 successfully
Version 7994 available
Downloaded version 7992 successfully

I would like for it to look like this.我希望它看起来像这样。

Version 7990 available
Downloaded version 7990 successfully
Version 7991 available
Downloaded version 7991 successfully
Version 7992 available
Downloaded version 7992 successfully
Version 7993 available
Downloaded version 7993 successfully
Version 7994 available
Downloaded version 7994 successfully

Apologies for the bad code, I hope somebody can help me!为错误的代码道歉,我希望有人能帮助我!

-Cheers -干杯

None of your functions justifies the async keyword (if you're not using await , using async is nonsense).你的函数都没有证明async关键字的合理性(如果你不使用await ,那么使用async是无稽之谈)。

But all of your functions are missing return .但是您的所有功能都缺少return You need to return the promises you create in a function.您需要返回您在 function 中创建的承诺。

Compare - every code path ends in return :比较 - 每个代码路径都以return结尾:

// returns a promise for whatever downloadFile() produces
function getFile(version) {
  return axios.request({ /* ... */ }).then((response) => {
    return downloadFile(version, response.data.location);
  }).catch(err => {
    return {error: "Download failed", version, err};
  });
}

// downloadFile() also returns a promise, so we return that
function downloadFile(version, data) {
  if (version && data) {
    const downloader = new Downloader({ /* ... */ });
    return downloader.download();
  }
  throw new Error("Invalid arguments");
};


// `downloads` will be an array of promises, we can wait for them with `Promise.all()`
function main() {
  const downloads = [];
  for (let i = 7990; i < 7995; i++) {
    downloads.push(getFile(i));
  }
  Promise.all(downloads).then((results) => {
    // all downloads are done
  }).catch(err => {
    console.log(err);
  });
}

You probably don't want to daisy-chain the downloads.您可能不想菊花链式下载。 You just want to wait until all are done.你只想等到一切都完成。 Promise.all() does that. Promise.all()就是这样做的。

You should use await on your axios request您应该在 axios 请求中使用 await

async function getFile(version)
{

  await axios.request({
    url: "https://****.****.com/v1/id/*****/version/" + version,
    method: "get",
    headers:{
        ContentType: 'application/json',
        Accept: "application/json",
        Cookie: ""
    } 
  }).then(function (response) {
      const placeData = response.data.location;
      //if placeData is null, then the version is not available
      if(placeData == null)
      {
        console.log("Version " + version + " not available");
        return;
      }
      console.log("Version " + version + " available");

      downloadFile(version, placeData)
      

  }).catch(function (error) {
      //console.log(error);
  });

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM