简体   繁体   中英

Synchronous “GET” in Node.JS

I am attempting to loop through images in a block of HTML and get the native width of each image. I have the DOM build perfectly and I'm using image-size module on NPM to retrieve the image widths.

The problem is it takes time to fetch the images and get their width, so the code continues processing before I've got the widths back. As a result I cannot adjust the widths in the HTML block because the functions run and complete before getting the first image back.

Anyway to stop the code from processing until this GET request finishes? I don't want the For-Loop to continue till the image completes.

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


    });

  }

My Full Code For Reference:

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

Create a function that returns a promise, or promisify the http class with middleware

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

Then iterate and store the promises

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

Using async eachSeries method

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM