Реализация обратного вызова / обещаний в 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
    });
};
Другие вопросы по тегам