J’ai un serveur de nœud ZombieJS sur Heroku qui récupère les données d’Internet. Le code serveur est appelé depuis une boucle for
côté client. Chaque itération de la boucle effectue un appel au serveur, ce qui permet de gratter un zombie. Parfois, le serveur plante avec l’erreur ci-dessous. Cela n’arrive que lorsqu’il y a plus d’une itération de la boucle for
.
Comment rendre le code suffisamment robuste pour gérer plusieurs appels client simultanés, chacun avec une boucle for
.
Code:
var express = require('express'); var app = express(); var Browser = require('zombie'); // sortinged changing var to const; no difference var assert = require('assert'); app.set('port', (process.env.PORT || 5000)); var printMessage = function() { console.log("Node app running on " + app.get('port')); }; var getAbc = function(response, input) { var browser = new Browser(); browser.userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0'; browser.runScripts = true; var url = "http://www.google.com/ncr"; browser.visit(url, function() { browser.fill('q', input).pressButton('Google Search', function(){ // parsing number of results from browser object response.writeHead(200, {'Content-Type': 'text/plain'}); response.end(numberOfSearchResults); }); }); } var handleXyz = function(request, response) { getAbc(response, request.query.input); } app.listen(app.get('port'), printMessage); app.post('/xyz', handleXyz);
Erreur:
assert.js:86 throw new assert.AssertionError({ ^ No open window with an HTML document at Browser.field (/app/node_modules/zombie/lib/index.js:811:7) at Browser.fill (/app/node_modules/zombie/lib/index.js:903:24) at /app/cfv1.js:42:11 at done (/app/node_modules/zombie/lib/eventloop.js:589:9) at timeout (/app/node_modules/zombie/lib/eventloop.js:594:33) at Timer.listOnTimeout (timers.js:119:15)
J’ai un projet similaire utilisant HorsemanJS / PhantomJS qui échoue de la même manière (je suis bloqué là-dessus aussi!): Le serveur NodeJS ne peut pas gérer plusieurs utilisateurs
En général, je pense que vous devriez faire attention ou simplement éviter de générer beaucoup de requêtes non sollicitées vers des serveurs distants. De nombreux sites vont vous étrangler et / ou commencer à rejeter des connexions. Cela dit, je pense avoir trouvé la source du problème dans ce cas particulier.
J’ai testé l’extrait de code et dans ce cas particulier, Google réinitialisera la connexion si vous faites trop de demandes. Lorsque la connexion est réinitialisée, l’une des variables échoue pour une assertion.
L’erreur que je reçois lorsque la connexion est réinitialisée:
zombie TypeError: read ECONNRESET at zombie/lib/pipeline.js:89:15 at tryCatcher (zombie/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (zombie/node_modules/bluebird/js/release/promise.js:497:31) at Promise._settlePromise (zombie/node_modules/bluebird/js/release/promise.js:555:18) at Promise._settlePromise0 (zombie/node_modules/bluebird/js/release/promise.js:600:10) at Promise._settlePromises (zombie/node_modules/bluebird/js/release/promise.js:679:18) at Async._drainQueue (zombie/node_modules/bluebird/js/release/async.js:125:16) at Async._drainQueues (zombie/node_modules/bluebird/js/release/async.js:135:10) at Immediate.Async.drainQueues [as _onImmediate] (zombie/node_modules/bluebird/js/release/async.js:16:14) at processImmediate [as _immediateCallback] (timers.js:383:17)
J’obtiens votre erreur d’origine plus bas, mais la source du problème est en réalité à cause de ce qui précède. Lorsque ce qui précède se produit, document.documentElement devient une valeur false-y et entraîne par la suite que cette assertion dans zombie / lib / index.js de la fonction field échoue:
assert(this.document && this.document.documentElement, 'No open window with an HTML document');
Je pense que la solution la plus simple est de gérer l’erreur du côté client et d’essayer de la récupérer avec élégance.
Je vois que vous créez une nouvelle instance de l’object Navigateur pour chaque appel. Je suppose que l’ancien “navigateur” est toujours en train de se fermer ou n’a pas été traité par le ramasse-miettes lorsque le prochain appel tente d’en ouvrir un autre. Essayez de déplacer l’instanciation du navigateur en dehors de getAbc ()