Реализация обратного вызова / обещаний в Express.js
Я пишу приложение Express.js, используя рентген в качестве скребка, чтобы получить некоторую информацию.
Я хочу создать модель для каждого очищаемого веб-сайта (другой веб-сайт = разные данные / процедуры для очистки). Вот код модуля:
module.exports.getData = function(title){
var Xray = require('x-ray');
var x = Xray();
var url = "http://www.mywebsite.it/online/search?text="+title;
var scraped = '';
x(url, '.listing-products.listing-rows.clearfix h2.title',
[{
title: 'a',
link: 'a@href'
}]
)(function (err, obj) {
for (var i = obj.length - 1; i >= 0; i--) {
scraped += obj[i]['title'] + " "; //we get just the title of the links for now
};
sendScraped(scraped);
});
}
Проблема в том, что функция контроллера getData ничего не возвращает, потому что она вызывается, и выполнение продолжается, не дожидаясь завершения функции очистки ().
Я пытаюсь реализовать функцию обратного вызова sendScraped(scraped), чтобы заставить мой контроллер ждать завершения, но я не знаю, как вызвать его из модели. Вот что я попробовал в контроллере:
var mywebsite = require('../models/mywebsite')
exports.searchTitle = function(req, res) {
mywebsite.getData(req.params.title);
};
global.sendScraped = function endScraping(data) {
return res.send(data);
}
1 ответ
Я бы предложил вам изменить свой getData()
способ принять обратный вызов. Затем он может вызвать этот обратный вызов с очищенными данными:
module.exports.getData = function (title, callback) {
var Xray = require('x-ray');
var x = Xray();
var url = "http://www.mywebsite.it/online/search?text=" + title;
var scraped = '';
x(url, '.listing-products.listing-rows.clearfix h2.title', [{
title: 'a',
link: 'a@href'
}])(function (err, obj) {
if (err) return callback(err);
for (var i = obj.length - 1; i >= 0; i--) {
scraped += obj[i]['title'] + " "; //we get just the title of the links for now
};
callback(null, scraped);
});
}
Затем вы можете использовать это в вашем обработчике запросов следующим образом:
var mywebsite = require('../models/mywebsite')
exports.searchTitle = function(req, res) {
mywebsite.getData(req.params.title, function(err, scrapeData) {
if (err) {
// do something with error
} else {
res.send(scrapeData);
}
});
};
И вот версия с обещаниями:
var Xray = require('x-ray');
function xp(url, selector, args) {
return new Promise(function(resolve, reject) {
var x = Xray();
x(url, selector, args)(function(err, obj) {
if (err) {
reject(err);
} else {
resolve(obj);
}
});
});
}
module.exports.getData = function (title) {
var url = "http://www.mywebsite.it/online/search?text=" + title;
var selector = '.listing-products.listing-rows.clearfix h2.title';
return xp(url, selector, [{title: 'a', link: 'a@href'}]).then(function(obj) {
var scraped = "";
for (var i = obj.length - 1; i >= 0; i--) {
scraped += obj[i]['title'] + " "; //we get just the title of the links for now
}
return scraped;
});
}
Затем вы можете использовать это в вашем обработчике запросов следующим образом:
var mywebsite = require('../models/mywebsite');
exports.searchTitle = function(req, res) {
mywebsite.getData(req.params.title).then(function(scrapeData) {
res.send(scrapeData);
}, function(err) {
// handle error here
});
};