我有这个功能
function parseLink(link) {
var product;
request(link, function (error, response, body) {
if (!error && response.statusCode == 200) {
var $ = cheerio.load(body);
// title
var title = $('h1').text();
if (!title)
var title = $('title').text();
var description = $('meta[name="description"]').attr('content');
product = new Product(link.trim(), title.trim(), description.trim());
}
});
console.log(product);
return product;
}
我不明白为什么当我在请求电话之外执行 console.log(产品)时,我已经未完成但在里面,我可以看到我的产品。
我在javascript中学习了很多关于范围的事情,我不明白,我在顶部函数中定义了产品。 我需要返回这个变量来获取它在另一个函数中,如果在请求中返回我当然有一个未定义的所以我需要在外面做这个... 谢谢
答案 0 :(得分:0)
javascript不运行像c
或php
这样的代码,您可以确保下一行代码在前一代准备就绪时运行。在你的情况下,request
是一个异步函数,所以两行
console.log(product);
return product;
主要在request
功能准备就绪之前运行。在这种情况下,您不能仅从parseLink
函数返回一些值。你有两种可能性:
使用承诺: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
使用回调:
function parseLink(link, callback) {
var product;
request(link, function (error, response, body) {
if (!error && response.statusCode == 200) {
var $ = cheerio.load(body);
// title
var title = $('h1').text();
if (!title)
var title = $('title').text();
var description = $('meta[name="description"]').attr('content');
product = new Product(link.trim(), title.trim(), description.trim());
callback(product);
}
});
}
然后运行像
这样的代码parseLink('http://...', function(product) { /* do something with the product */ });
ps:回调的使用要容易得多,但在某些情况下,如果你在for
循环中运行它,你可以分开范围
答案 1 :(得分:0)
request
是异步调用,因此此过程被推送到事件队列,该队列将在当前调用堆栈完成后运行。 console.log
打印undefined
,因为这是未分配变量的默认值。
如果需要从异步调用中返回值,则必须使用回调或promise。以下是使用Promise:
的示例function parseLink(link) {
return new Promise((resolve, reject) => {
request(link, function(error, response, body) {
if (error) return reject(error);
if (response.statusCode !== 200) {
return reject(new Error('Not OK'));
}
var $ = cheerio.load(body);
var title = $('h1').text() || $('title').text();
var description = $('meta[name="description"]').attr('content');
var product = new Product(link.trim(), title.trim(), description.trim());
resolve(product);
});
});
}
parseLink('http://example.com')
.then(product => {
console.log(product);
})
.catch(error => {
console.error(error);
});