Node.JS 中的同步“GET”
Posted
技术标签:
【中文标题】Node.JS 中的同步“GET”【英文标题】:Synchronous "GET" in Node.JS 【发布时间】:2016-08-23 19:06:35 【问题描述】:我正在尝试遍历 html 块中的图像并获取每个图像的本机宽度。我已经完美地构建了 DOM,并且我在 NPM 上使用 image-size 模块来检索图像宽度。
问题是获取图像并获取它们的宽度需要时间,因此在我恢复宽度之前代码会继续处理。结果,我无法调整 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 src="http://xdesktopwallpapers.com/wp-content/uploads/2011/11-1/Searching-For-Something.jpg" /> and <img style="width:190px" 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');
);
【问题讨论】:
由于不清楚getProtocolVar.get()
方法返回什么,即承诺与否,回调中的一个简单计数器,并检查counter === elem_tags_length
以知道所有图像都已加载是一个选项跨度>
同步代码不是nodejs的编码方式,学习使用回调和promise。
您可以使用async.js
来管理回调和链接。 github.com/caolan/async
使用异步,eachSeries 方法。
@adeneo 很抱歉我忘记更新该代码。它是http
函数。任何想法如何使用承诺。在这种情况下。我对节点很陌生。
【参考方案1】:
创建一个返回承诺的函数,或使用中间件承诺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
);
【讨论】:
唯一的细节是你必须等待data
和end
事件。见davidwalsh.name/nodejs-http-request
感谢您的建议!我现在正在尝试。 @JuanMendes 我使用 data
和 end
但这不会阻止此 GET 之外的代码继续。
这里唯一的问题是我需要修改图像标签。因此,一旦for
循环继续,我就无法再返回并更新该图像,因为它完成并输出了“修改后的”HTML(在这种情况下没有改变)。
@DigitalMC 正如 adeneo 指出的那样,创建一个 Promise
,其中 cmets 指示返回一个 Promise
,在收到 end
事件之前不要解决该承诺
我能想到的Promise.all
不触发的唯一原因是,如果所有的承诺都没有得到解决,你一定是遗漏了什么,或者一个或多个图像没有做他们应该做什么等等。【参考方案2】:
使用异步 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
)
【讨论】:
酷,我会试试这些家伙。所以我把http.get(imgUrl, function (response)...
放在yourGetFunction
函数里面?
明白了,这就是我感到困惑的地方。 yourArray
是什么?如何将函数列表存储在数组中还是完全倒退?
yourArray 是您拥有的任何数组。在您的情况下,您有一个元素数组。 'elem_tags'。看看这个例子:jsfiddle.net/yLrnrpsc以上是关于Node.JS 中的同步“GET”的主要内容,如果未能解决你的问题,请参考以下文章