2016-04-28 77 views
1

我通過圖像試圖迴路HTML塊「GET」,讓每個圖像的原始寬度。我有完美的DOM構建,我在NPM上使用圖像大小模塊來檢索圖像寬度。同步在Node.js的

問題是,它需要時間來獲取圖像,並得到他們的寬度,因此代碼將繼續進行處理我已經得到了寬度回來。因此,我無法調整HTML塊中的寬度,因爲函數在獲取第一個圖像之前運行並完成。

無論如何以停止從處理代碼,直到此GET請求完成?我不希望For-Loop繼續到圖像完成。

var elem_tags = doc.getElementsByTagName("img"); 
    var elem_tags_length = elem_tags.length; 

    for (var i=0; i < elem_tags_length; i++) { 
    var imgUrl = options.elem_tags[i].getAttribute('src'); 
    http.get(imgUrl, function (response) { 

     // My Code To Manipulate <img> tags 
     var chunks = []; 
     response.on('data', function (chunk) { 
     chunks.push(chunk); 
     }).on('end', function() { 
     var buffer = Buffer.concat(chunks); 
     console.log(imgSize(buffer).width); // imgSize is a module from NPM. Disregard for our loop purposes. 
     }); 


    }); 

    } 

我的完整代碼參考:

var url = require('/usr/lib/node_modules/url'); 
var http = require('http'); 
var https = require('https'); 
var jsdom = require("/usr/lib/node_modules/jsdom").jsdom; 
var imgSize = require('/usr/lib/node_modules/image-size/'); 

var myhtml = '<img src="http://xdesktopwallpapers.com/wp-content/uploads/2011/11-1/Searching-For-Something.jpg" /> <div style="width:500px;border:2px;" id="mytestdiv"><p style="margin:40px;">Harry Potter <img src="https://sites01.lsu.edu/wp/lsupd/files/2011/01/poster1.jpg" style="width:900px" /> and <img width="999" src="http://xdesktopwallpapers.com/wp-content/uploads/2011/11-1/Searching-For-Something.jpg" /> and <img style="width:190px" width="190" src="http://xdesktopwallpapers.com/wp-content/uploads/2011/11-1/Searching-For-Something.jpg" /></p></div>'; 

function getImage(imgUrl) { 
    console.log('image loop'); 
    return new Promise(function(resolve, reject) { 
     http.get(imgUrl, function(err, result) { 
      if (err) return reject(err); 
      return resolve(result); 
     }); 
    }); 
} 

var doc = jsdom(myhtml); 
var doc = doc.parentWindow.document;  

var elem_tags = doc.getElementsByTagName("img"); 
var elem_tags_length = elem_tags.length; 
var promises = []; 

for (var i=0; i < elem_tags_length; i++) { 

    var imgUrl = elem_tags[i].getAttribute('src'); 

    var promise = getImage(imgUrl).then(function(response) { 
     // My Code To Manipulate <img> tags .... return promise if async 
    }); 

    promises.push(promise); 

} 

Promise.all(promises).then(function() { 
    console.log('done'); 
}); 
+0

由於目前還不清楚是什麼'getProtocolVar.get()'方法返回,即承諾或沒有,回調裏面一個簡單的計數器,並檢查計數器'== = elem_tags_length'知道所有圖像加載是一個選項 – adeneo

+3

同步代碼不是代碼nodejs的方式,學會使用回調和承諾。 –

+1

您可以使用'async.js'來管理回調和鏈接。 https://github.com/caolan/async –

回答

2

創建一個返回一個承諾的功能,或promisify的http類中間件

function getImage(imgUrl) { 
    return new Promise(function(resolve, reject) { 
     http.get(imgUrl, function(response) { 
      var image = ''; 

      response.on('data', function(data) { 
       image += data; 
      }); 

      response.on('end', function() { 
       return resolve(image); 
      }); 

      response.on('error', reject); 
     }); 
    }); 
} 

然後遍歷和存儲承諾

var elem_tags = doc.getElementsByTagName("img"); 
var elem_tags_length = elem_tags.length; 
var promises = []; 

for (var i=0; i < elem_tags_length; i++) { 

    var imgUrl = options.elem_tags[i].getAttribute('src'); 

    var promise = getImage(imgUrl).then(function(response) { 
     // My Code To Manipulate <img> tags .... return promise if async 
    }); 

    promises.push(promise); 

} 

Promise.all(promises).then(function() { 
    // all done 
}); 
+0

唯一的細節是你必須等待'data'和'end'事件。請參閱https://davidwalsh.name/nodejs-http-request –

+0

感謝您的想法!我現在正在嘗試。 @JuanMendes我使用'data'和'end',但是這並不能阻止GET之外的代碼繼續。 – DigitalMC

+0

這裏唯一的問題是我需要修改圖片標籤。因此,一旦'for'循環繼續,我不能再返回並更新該映像,因爲它完成並輸出'modified'HTML(在這種情況下,它沒有改變)。 – DigitalMC

1

使用異步eachSeries方法

async.eachSeries(yourArray, function(item, cb) { 
    http.get(imgUrl, function (result) { 
    //Do whatever you want with result 
    //call the cb function of the async to continue the loop 
    cb(); 

    }) 
}, function(){ 
    //Once your loop is finished, this function will be called 
}) 
+0

很酷,我會給這個傢伙一個鏡頭。所以我把'http.get(imgUrl,函數(響應)...'在'yourGetFunction'函數內部? – DigitalMC

+0

不,不用你的http get替換你的GetFunction。 讓我編輯.... – yBrodsky

+0

現在在這裏是什麼'yourArray'?我如何在數組中存儲一個函數列表或者我完全向後? – DigitalMC