2015-09-15 24 views
7

ho costruito uno script nodo semplice utilizzando nightmare.js per raschiare siti webUtilizzare Nightmare.js senza sintassi ES6 e cedere

var Nightmare = require('nightmare'); 
var vo = require('vo'); 

vo(run)(function(err, result) { 
    if (err) throw err; 
}); 

function *run() { 
    var x = Date.now(); 
    var nightmare = Nightmare(); 
    var html = yield nightmare 
    .goto('http://google.com') 
    .evaluate(function() { 
     return document.getElementsByTagName('html')[0].innerHTML; 
    }); 

    console.log("done in " + (Date.now()-x) + "ms"); 
    console.log("result", html); 

    yield nightmare.end(); 
} 

voglio correre questo in un ambiente che utilizza una versione precedente di nodo, che non lo fa supporta le funzionalità ES6. Non ci sono esempi sulla pagina Github su come fare questo senza la parola chiave "rendimento".

ho trovato un esempio di utilizzo senza la sintassi ES6 qui: Webscraping with nightmare

ho scritto in questo modo:

var night = new Nightmare() 
.goto('http://www.google.com') 
.evaluate(function() { 
    return document.getElementsByTagName('html')[0].innerHTML; 
},function (html) { 
    console.log("result", html); 
    } 
) 
.run(function (err, nightmare) { 
    if (err) return console.log(err); 
    console.log('Done!'); 
}); 

Esso non va in crash, ma la funzione di registrazione risultato non è mai chiamato.

Con la sintassi del rendimento, ottenere il valore restituito da "Valuta" è piuttosto semplice, ma senza di esso, non ho trovato alcun modo per farlo.

UPDATE Riportato questo grazie alla risposta accettata e ai suoi commenti. Esso utilizza 'Q' e lavora a versioni precedenti dei nodi a 0,12:

var Nightmare = require('nightmare'); 

var Promise = require('q').Promise; 

var x = Date.now(); 
var nightmare = Nightmare(); 
Promise.resolve(nightmare 
    .goto('http://google.com') 
    .evaluate(function() { 
     return document.getElementsByTagName('html')[0].innerHTML; 
})).then(function(html) { 
    console.log("done in " + (Date.now()-x) + "ms"); 
    console.log("result", html); 
    return nightmare.end(); 
}).then(function(result) { 

}, function(err) { 
    console.error(err); // notice that `throw`ing in here doesn't work 
}); 
+1

Usando [babel-node] (https://babeljs.io/docs/usage/cli/# babel-node) potrebbe essere una soluzione più semplice, a seconda del caso d'uso. È fondamentalmente un wrapper che traspone il codice ES6 in ES5 prima di eseguirlo. –

risposta

12

La documentazione sono orribili, ma sembra che Nightmare si basa su thenables. Non ho trovato molte informazioni sull'interfaccia di callback, ma ciò avrebbe comunque portato a una piramide di indentazione.

Quindi la soluzione migliore è utilizzare le promesse, basta scegliere any library che segue lo standard ES6 (sono utilizzabili anche in ambienti non ES6).

Si può facilmente trasformare il vostro codice di generatore lineare in una catena promessa, basta sostituire ogni yield da un then chiamata:

var Nightmare = require('nightmare'); 
var Promise = require('…'); 

var x = Date.now(); 
var nightmare = Nightmare(); 
Promise.resolve(nightmare 
    .goto('http://google.com') 
    .evaluate(function() { 
     return document.getElementsByTagName('html')[0].innerHTML; 
})).then(function(html) { 
    console.log("done in " + (Date.now()-x) + "ms"); 
    console.log("result", html); 
    return nightmare.end(); 
}).then(function(result) { 
    … 
}, function(err) { 
    console.error(err); // notice that `throw`ing in here doesn't work 
}); 
+0

Quale libreria della lista hai usato in questo preciso esempio? Ho provato con "q" senza successo – Rayjax

+0

Ah, 'Q' ha convenzioni di chiamata legacy (era una delle prime librerie). Dovresti fare 'Q.Promise' invece di' Promise' e ​​'Q' invece di' Promise.resolve'. – Bergi

+0

Funziona ora :) – Rayjax

Problemi correlati