Nodejs http.get异步带来的困扰
Nodejs http.get异步带来的困扰
webot.set(‘news’,{
pattern: /new.*/i,
handler:function(info){
news = [];
http.get(address, function(res){
var data = ‘’;
res.on('data' , function(d){
data += d;
}).on('error',function(err){
console.log(err.message);
});
res.on('end' , function(){
//分析HTML找到需要的内容,并赋给news
var $ = cheerio.load(data);
$('table').eq(2).find('table').eq(1).find('tr').slice(1,13)
.each(function(index,ele){
news[index] = {
title:this.find('a').first().text(),
url:this.find('a').attr('href')
};
})
}).on('error',function(err){
console.log(err.message);
});
}).on('error', function(err){
console.log(err.message);
});
return news;
}
});
用之前公布的微信ROBOT做一个微信机器人。分析HTML然后返回结果,作一个简单的爬虫。但是news被直接返回了,还没等到http.get执行完,这个时候应该怎么办,有什么异步返回方法么?
在使用 Node.js 的 http.get
方法时,经常会遇到异步操作带来的困扰,特别是在处理依赖于异步操作的结果时。在你提供的代码中,news
数组是在异步请求完成之前就被直接返回了,因此它始终是空的。为了解决这个问题,我们可以使用回调函数或者 Promise 来管理异步操作。
使用回调函数
首先,我们可以通过回调函数来处理异步操作的结果。下面是修改后的代码:
const http = require('http');
const cheerio = require('cheerio');
webot.set('news', {
pattern: /new.*/i,
handler: function (info, cb) {
const news = [];
http.get(address, function (res) {
let data = '';
res.on('data', function (d) {
data += d;
}).on('error', function (err) {
console.log(err.message);
});
res.on('end', function () {
// 分析 HTML 找到需要的内容,并赋给 news
const $ = cheerio.load(data);
$('table').eq(2).find('table').eq(1).find('tr').slice(1, 13)
.each(function (index, ele) {
news[index] = {
title: $(this).find('a').first().text(),
url: $(this).find('a').attr('href')
};
});
// 将结果通过回调函数传递出去
cb(null, news);
}).on('error', function (err) {
console.log(err.message);
cb(err, null);
});
}).on('error', function (err) {
console.log(err.message);
cb(err, null);
});
}
});
// 使用回调函数获取新闻数据
webot.on('news', function (info, cb) {
webot.execute('news', info, function (err, result) {
if (err) {
console.error(err);
} else {
console.log(result); // 输出解析后的新闻数据
}
});
});
使用 Promise
另一种更现代的方法是使用 Promise,这可以使得代码更加简洁和易于理解。以下是使用 Promise 的示例:
const http = require('http');
const cheerio = require('cheerio');
webot.set('news', {
pattern: /new.*/i,
handler: function (info) {
return new Promise((resolve, reject) => {
const news = [];
http.get(address, function (res) {
let data = '';
res.on('data', function (d) {
data += d;
}).on('error', function (err) {
console.log(err.message);
reject(err);
});
res.on('end', function () {
// 分析 HTML 找到需要的内容,并赋给 news
const $ = cheerio.load(data);
$('table').eq(2).find('table').eq(1).find('tr').slice(1, 13)
.each(function (index, ele) {
news[index] = {
title: $(this).find('a').first().text(),
url: $(this).find('a').attr('href')
};
});
resolve(news);
}).on('error', function (err) {
console.log(err.message);
reject(err);
});
}).on('error', function (err) {
console.log(err.message);
reject(err);
});
});
}
});
// 使用 Promise 获取新闻数据
webot.on('news', async function (info) {
try {
const result = await webot.execute('news', info);
console.log(result); // 输出解析后的新闻数据
} catch (err) {
console.error(err);
}
});
在这两种方法中,我们都确保了在异步请求完成之后再返回结果,从而避免了直接返回尚未完成的数据的问题。
看看async库
正常执行顺序就是这样的, 常用的方案是在 handler 后边传一个回调函数 (info, callback) get 请求完成以后调用回调函数, 把后边的操作写在回调函数函数体里边
我看了一下源码的例子,他在里面用了中间件一层一层的处理,只要传一个next,调用后交给最后处理的函数就可以。
在处理 Node.js 中的异步操作时,http.get
是一个典型的异步调用。在你的代码中,news
变量被立即返回,而此时 http.get
还没有完成数据获取。这会导致 news
为空。
为了解决这个问题,你可以使用回调函数或 Promise 来处理异步操作。以下是使用 Promise 的示例代码:
const http = require('http');
const cheerio = require('cheerio');
webot.set('news', {
pattern: /new.*/i,
handler: function (info) {
return new Promise((resolve, reject) => {
http.get(address, function (res) {
let data = '';
res.on('data', function (d) {
data += d;
}).on('error', function (err) {
console.log(err.message);
reject(err);
});
res.on('end', function () {
try {
const $ = cheerio.load(data);
const news = [];
$('table').eq(2).find('table').eq(1).find('tr').slice(1, 13).each(function (index, ele) {
news.push({
title: $(this).find('a').first().text(),
url: $(this).find('a').attr('href')
});
});
resolve(news);
} catch (err) {
reject(err);
}
});
}).on('error', function (err) {
console.log(err.message);
reject(err);
});
});
}
});
// 使用示例
webot.handle({ message: 'news' }).then(result => {
console.log(result);
}).catch(error => {
console.error(error);
});
在这个示例中,我们使用 Promise
包装了 http.get
操作,并在 http.get
完成后通过 resolve
返回结果。这样,你可以确保在 news
数据准备好后再进行后续处理。