简体   繁体   中英

How to reset forEach() function if statement is matched [NodeJS]

const downloadurl = ['url1', 'url2']
const filename = 'run.jar'

downloadurl.forEach((urls) => {
    https.get(urls, (httpsres) => {
        const path = `${installationdirectory}/${filename}`
        const filePath = fs.createWriteStream(path);
        httpsres.pipe(filePath);
        filePath.on('finish',() => {

            filePath.close();
            const filesize = fs.statSync(path).size
            // Verify if the size of the file is smaller than 1Kb
            if((filesize / 1024) < 1) return;

            // Want to skip this console.log if the file size is smaller than 1Kb and try with the other downloadurl (Hence why the downloadurl.forEach)
            console.log('File downloaded!'); 


        })
    })
})

Basically, I'm using the https module from NodeJS which doesn't give an error if the download url doesn't exist, as it just creates a 1-byte file with the run.jar name instead. So, I want to make it stop executing code and try to download with the other URL if the size of the file is smaller than 1Kb, any ideas?

  1. you can use every() loop. and when you want to break the loop just don't return anything.

// Prints "1, 2, 3"
[1, 2, 3, 4, 5].every(v => {
  if (v > 3) {
    return false;
  }

  console.log(v);
  // Make sure you return true. If you don't return a value, `every()` will stop.
  return true;
});
  1. or you can change length of array using third
const myNums = [1, 2, 3, 4, 5];
myNums.forEach((v, index, arr) => {
  console.log(v);
  if (val > 3) {
    arr.length = index + 1; // Behaves like `break`
  }
}

If using a callback structure, as you are at the moment, you could try a recursive function to try further downloads.

function tryDownload(downloadUrls):
    // try download the first
    https.get(downloadUrls[0], (res) => {
        // read it, etc
        // ...

        // if too small, try the next urls
        if ((filesize / 1024) < 1)
            tryDownload(downloadUrls.slice(1));
        else
            // success!
            // ...
    })

You may find it clear to restructure this as an asynchronous function, though. In pseudocode:

    for each url in download urls
        res = await download url
        if res indicates success
            handle the res
            return

Used @Matt's answer as it was the simplest one to implement (And I didn't know that the HTTPS module does have a response to check the status code). Thanks everyone that answered tho ^^

    const downloadurl = ['url1', 'url2']
    const filename = 'run.jar'
    
    downloadurl.forEach((urls) => {
        https.get(urls, (httpsres) => {
            if(httpsres.statusCode !== 200) {
                return console.log(`Attempt of downloading failed with ${httpsres.statusCode} error! Retrying with another download URL`);
            } else {
    
            const path = `${installationdirectory}/${filename}`
            const filePath = fs.createWriteStream(path);
            httpsres.pipe(filePath);
            filePath.on('finish',() => {
    
                filePath.close();
                const filesize = fs.statSync(path).size
                // Verify if the size of the file is smaller than 1Kb
                if((filesize / 1024) < 1) return;
    
                // Want to skip this console.log if the file size is smaller than 1Kb and try with the other downloadurl (Hence why the downloadurl.forEach)
                console.log('File downloaded!'); 
    
            })
            }
        })
    })
    ```

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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