2017-05-25 5 views
0

Ich habe vor kurzem mit der Entwicklung einer Node js-Anwendung begonnen und Selenium in einem Controller verwendet, um eine Liste von Elementen von einer Webseite abzurufen und die abgerufene Liste von Elementen als JSON-Antwort zurückzugeben.Rückgabeliste von Objekten mit Knoten js

exports.read_all_products = function (req, res) { 
    var driver = new webdriver.Builder().forBrowser('phantomjs').build(); 
    driver.get('https://www.test.com/products?PC=' +req.params.category);  
    driver.wait(until.elementLocated(By.className('product-slide-all')), 20000, 'Could not locate the element within the time specified'); 

    driver.findElements(By.className("product-slide-all")).then(function (elements) { 
     var arr = []; 
     elements.forEach(function (element) { 
     element.getAttribute("innerHTML").then(function (html) { 
      const dom = new JSDOM(html); 
      var obj = new Object(); 
      obj.product_name = dom.window.document.querySelector(".product-name").textContent; 
      obj.product_code = dom.window.document.querySelector(".product-code").textContent; 
      obj.price = dom.window.document.querySelector(".product-price").textContent; 
      arr.push(obj); 
     }); 
    }); 
    res.json(arr); 
    }); 
} 

Problem ist, ich bekomme immer eine leere JSON-Antwort, obwohl Elemente zum Array hinzugefügt wurden. Ich möchte den richtigen Umgang mit diesem Szenario wissen.

Danke.

+0

Können Sie versuchen, Ihre 'res.json (arr);' one level up? (vor dem '});')? –

+0

Nein, dann wird ein Fehler angezeigt, der besagt, dass die Header nach dem Senden nicht mehr gesetzt werden können. – Lakmal

+0

Ohh. Können Sie in diesem Fall versuchen, Ihre 'res.json (arr);' als 'JSON.parse (JSON.stringify (arr))' 'umzudefinieren? –

Antwort

0

Schließlich konnte ich es mit Hilfe von webdriver.promise.map bekommen zu arbeiten.

Die HTML-Extraktion des Webtreibers wurde in eine separate Funktion verschoben.

var findItems = function (category) { 
var driver = new webdriver.Builder().forBrowser('phantomjs').build(); 
var map = webdriver.promise.map; 
driver.get('https://www.test.com?PC=' + category); 
driver.wait(until.elementLocated(By.className('product-slide-all')), 30000, 'Could not locate the element within the time specified'); 
    var elems = driver.findElements(By.className("product-slide-all")); 
     return map(elems, elem => elem.getAttribute("innerHTML")).then(titles => { 
     return titles; 
    }); 
} 

nennen es dann von Response-Handling-Funktion wie unten,

exports.read_all_products = function (req, res) { 
findItems(req.params.category).then(function (html) { 
    var value; 
    var arr = []; 
    Object.keys(html).forEach(function (key) { 
     value = html[key]; 
     const dom = new JSDOM(value); 
     var obj = new Object(); 
     obj.product_name = dom.window.document.querySelector(".product-name").textContent; 
     obj.product_code = dom.window.document.querySelector(".product-code").textContent; 
     obj.price = dom.window.document.querySelector(".product-price").textContent; 
     arr.push(obj); 
    }); 
    res.json(arr); 
}) 
}; 

es in this stack overflow answers beschrieben wird.

0

Es scheint, als wäre das Problem, weil Selenium einen asynchronen Prozess ausführt, daher wird die Antwort sofort zurückgegeben, da nichts blockiert wird.

findElements gibt ein Versprechen zurück, von dem Sie die Antwort zurücksenden müssen.

Werfen Sie einen Blick auf How do I return the response from an asynchronous call?