In Node.js possiamo effettuare il download delle risorse statiche di un'app.

Useremo le Promise ed il costrutto async/await per scaricare e salvare in locale dei file JavaScript e CSS.


'use strict';

const fs = require('fs');
const path = require('path');
const https = require('https');
const ABSPATH = path.dirname(process.mainModule.filename) + '/';

const assets = [
    {
        src: ABSPATH + 'public/js/',
        name: 'jquery.min.js',
        url: 'https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js'
    },
    {
        src: ABSPATH + 'public/js/',
        name: 'bootstrap.min.js',
        url: 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js'
    },
    {
        src: ABSPATH + 'public/css/',
        name: 'bootstrap.min.css',
        url: 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'
    }
];

const downloadAsset = (url, src, localName) => {
    return new Promise((resolve, reject) => {
        let dest = src + localName;
        if( !fs.existsSync(dest) ) {
            let asset = fs.createWriteStream( dest );
            let request = https.get(url, response => {
                response.pipe(asset);
                asset.on('finish', () => {resolve(localName)});
            }).on('error', err => {
                fs.unlinkSync(dest);
                reject(err);
            });
        } else {
            resolve(localName);
        }
    });
};

const createAssets = () => {
    let downloads = [];
    assets.forEach(asset => {
        downloads.push(downloadAsset(asset.url, asset.src, asset.name));
    });
    return Promise.all(downloads);
};

const init = async () => {
    try {
        let assetsCreated = await createAssets();
        assets.forEach( asset => { console.log( 'Scaricato il file  ' + asset.name); });
    } catch(err) {
        console.log(err);
    }
};

init();

Ciascun download (una Promise) viene eseguito in parallelo tramite il metodo Promise.all(). Un download non è altro che una richiesta HTTP remota
il cui output è uno stream di dati che viene reindirizzato tramite il metodo .pipe() allo stream in scrittura creato con il metodo
.createWriteStream(). Nella gestione degli stream di dati è fondamentale usare gli eventi per poter effettuare operazioni come la
risoluzione di una Promise.