2013-03-08 4 views
9

Ich benutze versuchen, nodejs und phantomjs auf der Serverseite für SEO unserer Website zu verwenden. Obwohl Ajax funktioniert, kann ich keine benutzerdefinierten Versprechungen ausführen, die ich in meinem Code verwendet habe. Wie kann ich phantomJS warten lassen, bis die Versprechen gelöst sind? Unten ist was ich codiert habe.Wie führe ich jQuery-Versprechen in phantomJS aus?

$('body').addClass('before-dom-ready'); 

$(function() { 
    $('body').addClass('after-dom-ready'); 

    var dfrd = $.Deferred(), 
      promise = dfrd.promise(); 

    setTimeout(function() { 
     dfrd.resolve(); 
    }, 5000); 

    promise.done(function() { 
     $('body').addClass('promise-executed'); 
    }); 

}); 

PhantomJS fügt 'vor-dom-ready' und 'After-dom-ready' Klasse, aber ich bin nicht in der Lage auf dem Körper 'Versprechen ausgeführte' Klasse zu erhalten.

+0

Ist es möglich, Ihr vollständiges phantomJS-Skript (sowie den vollständigen Code aller anderen Dateien, von denen es abhängt) zu sehen. I.e. so können wir das Problem leicht reproduzieren. –

+0

Zu welchem ​​Zeitpunkt und wie überprüfen Sie, ob die Klasse 'promise-executed' hinzugefügt wurde oder nicht? Welche Art von Debugging haben Sie beispielsweise durchgeführt? Haben Sie versucht, einen 'console.log'-Aufruf nach dem' dfrd.resolve() 'zu platzieren? Hast du diesen Code in einem normalen Browser ausprobiert, mit anderen Worten, was lässt dich glauben, dass es ein PhantomJS-Problem ist? –

Antwort

4

PhantomJs wartet nicht automatisch auf das Ende aller ausstehenden Skripts. WebPage # onLoadFinished wird für das Onload-Ereignis aufgerufen.

Wie bei den meisten Skripten ist die Idee hier zu warten, bis "etwas" getan oder wahr ist. Ich empfehle Ihnen dringend, waitfor.js zu testen. Es ist wirklich wichtig, dieses Beispiel in PhantomJs zu verstehen.

Ich nehme an, Ihr Beispiel ist ein Beispiel, aber lassen Sie mich eine Antwort vorschlagen.

HTML-Seite

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.0.min.js"></script> 
    <title>Test</title> 
</head> 
<body id="body"> 

    <script type="text/javascript"> 
     //alert('hello'); 
     $('body').addClass('before-dom-ready'); 

     $(function() { 
      $('body').addClass('after-dom-ready'); 

      var dfrd = $.Deferred(), 
        promise = dfrd.promise(); 

      setTimeout(function() { 
       dfrd.resolve(); 
      }, 5000); 

      promise.done(function() { 
       $('body').addClass('promise-executed'); 
       $('body').text('Hello World !'); 
      }); 

     }); 
    </script> 
</body> 
</html> 

PhantomJS Script

var page = require('webpage').create(); 
var system = require('system'); 

function waitFor(testFx, onReady, timeOutMillis) { 
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 10000, //< Default Max Timout is 10s 
     start = new Date().getTime(), 
     condition = false, 
     interval = setInterval(function() { 
      if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { 
       // If not time-out yet and condition not yet fulfilled 
       condition = (typeof (testFx) === "string" ? eval(testFx) : testFx()); //< defensive code 
      } else { 
       if (!condition) { 
        // If condition still not fulfilled (timeout but condition is 'false') 
        //console.log("'waitFor()' timeout"); 
        typeof (onReady) === "string" ? eval(onReady) : onReady(); 
        clearInterval(interval); 
        //phantom.exit(1); 
       } else { 
        // Condition fulfilled (timeout and/or condition is 'true') 
        console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); 
        typeof (onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled 
        clearInterval(interval); //< Stop this interval 
       } 
      } 
     }, 500); //< repeat check every 500ms 
}; 

if (system.args.length != 1) { 
    console.log('invalid call'); 
    phantom.exit(1); 
} else { 
    //adapt url to your context 
    page.open('http://localhost:9231/demo.html', function (status) { 
     if (status !== 'success') { 
      console.log('Unable to load the address!'); 
      phantom.exit(); 
     } else { 
      waitFor(
       function() { 
        return page.evaluate(function() { 
         return $('body').hasClass('promise-executed'); 
        }) > 0; 
       }, 
       function() { 
        page.render('page.png'); 
        phantom.exit(); 
       }, 10000); 
     } 
    }); 
} 

Grundsätzlich wird waitFor alle 500 ms überprüfen, ob Körper eine Klasse 'promise-executed' benannt hat.

+0

Danke für die ausführliche Antwort .. Ich muss ein bisschen mehr lesen, bevor Sie in meine Tests einbeziehen, aber das scheint vernünftig und gut dokumentiert .. –

+0

ja, das funktioniert für mich. Hoffe, das wird dir auch helfen. – Cybermaxs