2016-04-28 75 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