2013-03-26 2 views
1

Я работаю на простое приложение, с помощью Node.js, который необходимо выполнить следующие действия при введении действительное URL-адресЗагрузка N количество удаленных файлов с помощью Node.js синхронно

  1. извлечения HTML удаленной страницы , сохраните его локально.
  2. Spider HTML (используя cheerio) и записывать все ссылки на JS и CSS.
  3. Сделайте HTTP-запрос для каждого файла JS/CSS и сохраните его на сервере по имени файла.
  4. Закройте файлы html, css и js и передайте полученный файл в браузер.

У меня 1 и 2 рабочих, а первая половина № 3, но у меня проблемы с синхронностью загрузки. Мой код работает слишком быстро и генерирует имена файлов для CSS и JS-файлов, но ни один из содержимого. Я предполагаю, что это потому, что мой код не синхронный. Проблема в том, что я не знаю заранее, сколько файлов может быть, и все они должны быть там до того, как файл ZIP может быть сгенерирован.

Вот поток моего приложения, поскольку он в настоящее время существует. Я отказался от вспомогательных методов, поскольку они не влияют на синхронность. Может ли кто-нибудь из вас внести свой вклад в то, что я должен делать?

http.get(fullurl, function(res) { 
    res.on('data', function (chunk) { 
     var $source = $(''+chunk), 
      js = getJS($source, domain), 
      css = getCSS($source, domain), 
      uniqueName = pw(), 
      dir = [baseDir,'jsd-', uniqueName, '/'].join(''), 
      jsdir = dir + 'js/', 
      cssdir = dir + 'css/', 
      html = rewritePaths($source); 

     // create tmp directory 
     fs.mkdirSync(dir); 

     console.log('creating index.html'); 

     // save index file 
     fs.writeFileSync(dir + 'index.html', html); 

     // create js directory 
     fs.mkdirSync(jsdir); 

     // Save JS files 
     js.forEach(function(jsfile){ 
      var filename = jsfile.split('/').reverse()[0]; 
      request(jsfile).pipe(fs.createWriteStream(jsdir + filename)); 
      console.log('creating ' + filename); 
     }); 

     // create css directory 
     fs.mkdirSync(cssdir); 

     // Save CSS files 
     css.forEach(function(cssfile){ 
      var filename = cssfile.split('/').reverse()[0]; 
      request(cssfile).pipe(fs.createWriteStream(cssdir + filename)); 
      console.log('creating ' + filename); 
     }); 

     // write zip file to /tmp 
     writeZip(dir,uniqueName); 

     // https://npmjs.org/package/node-zip 
     // http://stuk.github.com/jszip/ 

    }); 
}).on('error', function(e) { 
    console.log("Got error: " + e.message); 
}); 
+1

a) Я не думаю, что есть способ сделать синхронный http-запрос в узле b) Выполнение всего этого синхронно было бы очень плохой идеей – DeadAlready

+0

@DeadAlready: +1 для плохой идеи, хотя есть https://npmjs.org/package/httpsync – Bergi

+0

DeadAlready необходимо, чтобы все файлы CSS/JS, указанные в файле index.html, загружались так, чтобы их можно было закрепить. Выполняется ли это синхронно или асинхронно, не имеет значения, когда все файлы должны присутствовать перед продолжением. – commadelimited

ответ

7

Как вы скачиваете файл через модуль запроса является асинхронным

request(cssfile).pipe(fs.createWriteStream(cssdir + filename)); 

вместо загрузки, как, что вам нужно сделать, как это создать отдельную функцию

function download (localFile, remotePath, callback) { 
var localStream = fs.createWriteStream(localFile); 

var out = request({ uri: remotePath }); 
out.on('response', function (resp) { 
    if (resp.statusCode === 200){ 
     out.pipe(localStream); 
     localStream.on('close', function() { 
      callback(null, localFile); 
     }); 
    } 
    else 
     callback(new Error("No file found at given url."),null); 
}) 
}; 

вам нужно использовать асинхронный модуль по колану https://github.com/caolan/async для

// Save JS files 
    async.forEach(js,function(jsfile,cb){ 
     var filename = jsfile.split('/').reverse()[0]; 
     download(jsdir + filename,jsfile,function(err,result){ 
      //handle error here 

      console.log('creating ' + filename); 
      cb(); 
     })       
    },function(err){ 
    // create css directory 
    fs.mkdirSync(cssdir); 

    // Save CSS files 
    css.forEach(function(cssfile){ 
     var filename = cssfile.split('/').reverse()[0]; 
     request(cssfile).pipe(fs.createWriteStream(cssdir + filename)); 
     console.log('creating ' + filename); 
    }); 

    // write zip file to /tmp 
    writeZip(dir,uniqueName); 
    }); 
+0

для файлов css вам нужно сделать то же самое, что и для файлов javascript. –

+0

Благодарим за помощь @khurrum. – commadelimited