2013-03-08 14 views
9

私は、サイトのSEOのサーバー側でnodejsとphantomjsを使用しようとしています。 Ajaxはうまく動作しますが、自分のコードで使用したカスタムの約束を実行することはできません。約束事が解決されるまで、どのようにしてファントムジャムを待つか。 以下は私がコーディングしたものです。phantomJSでjQueryの約束事を実行するにはどうすればいいですか?

$('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「前-DOM-準備」追加し、「後のDOM対応の」クラスが、私は体に「約束-実行」クラスを取得できませんよ。

+0

完全なphantomJSスクリプト(およびそれが依存する他のファイルの完全なコード)を見ることは可能ですか?私。問題を容易に再現することができます。 –

+0

いつ、どのようにして 'promise-executed'クラスが追加されたかどうか確認していますか?あなたが 'dfrd.resolve()'の後に 'console.log'呼び出しを置こうとしたなど、どんな種類のデバッグをしましたか?このコードを通常のブラウザで試したことがありますか。言い換えれば、PhantomJSの問題だと思いますか? –

答えて

4

PhantomJsは、保留中のすべてのスクリプトの終了を自動的に待機しません。 WebPage#onLoadFinishedはonloadイベントで呼び出されます。

スクリプトのほとんどは、「何か」が成立するまで待つことです。 waitfor.jsをテストすることを強くお勧めします。 PhantomJsのこの例を理解することは本当に重要です。

あなたの例が一例だとしますが、私は答えを提案しましょう。

HTMLページ・

<!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スクリプト

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); 
     } 
    }); 
} 

体が'promise-executed'という名前のクラスを持っている場合は基本的に、waitForは500ms毎にチェックします。

+0

詳細な返答をいただきありがとうございます。私のテストに組み込む前にもう少し読書をしなければなりませんが、これは合理的で十分に文書化されています。 –

+0

はい、これは私のために働く。これがあなたにも役立つことを願っています。 – Cybermaxs

関連する問題