2013-03-26 99 views
1

我正在使用Node.js的一個簡單的應用程序,它需要做的給予有效的URL如何使用Node.js的遠程文件下載N多同步

  1. 檢索遠程頁面的HTML以下時,在本地保存。
  2. Spider HTML(使用cheerio)並記錄所有JS和CSS文件引用。
  3. 爲每個JS/CSS文件發出HTTP請求並通過文件名將其保存到服務器。
  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 2013-03-26 07:00:01

+0

@DeadAlready:+1對於壞主意,儘管存在https://npmjs.org/package/httpsync – Bergi 2013-03-26 09:25:44

+0

DeadAlready,要求必須下載index.html中引用的所有CSS/JS文件,以便將它們壓縮。在進行之前,所有文件必須存在時,無論是同步還是異步完成都沒有區別。 – commadelimited 2013-03-26 13:18:44

回答

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

你需要通過colan使用異步模塊https://github.com/caolan/async for

// 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文件 – 2013-03-26 08:57:13

+0

謝謝你的幫助@khurrum。 – commadelimited 2013-04-03 21:49:05