2013-03-08 27 views
9

Tôi đang sử dụng cố gắng sử dụng nodejs và phantomjs ở phía máy chủ cho SEO của trang web của chúng tôi. Trong khi ajax hoạt động tốt, tôi không thể thực hiện các lời hứa tùy chỉnh mà tôi đã sử dụng trong mã của mình. Làm thế nào để làm cho phantomJS đợi cho đến khi các lời hứa được giải quyết. Dưới đây là những gì tôi đã mã hóa.Làm cách nào để thực thi các lời hứa jQuery trong phantomJS?

$('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 thêm lớp 'trước khi sẵn sàng' và 'sau khi đã sẵn sàng', nhưng tôi không thể nhận lớp 'hứa hẹn được thực hiện' trên cơ thể.

+0

Có thể xem tập lệnh ảo đầy đủ của bạn (cũng như mã đầy đủ của bất kỳ tệp nào khác mà nó phụ thuộc vào). I E. để chúng tôi có thể dễ dàng tái tạo vấn đề. –

+0

Vào thời điểm nào, và làm cách nào, bạn kiểm tra xem liệu lớp 'lời hứa thực thi' có hay chưa được thêm vào không? Ví dụ, bạn đã thử thực hiện lệnh gọi 'console.log' sau' dfrd.resolve() 'như thế nào? Bạn đã thử mã này trong một trình duyệt thông thường hay nói cách khác, điều gì khiến bạn nghĩ đó là một vấn đề về PhantomJS? –

Trả lời

4

PhantomJ không tự động chờ kết thúc của tất cả các tập lệnh đang chờ xử lý. WebPage # onLoadFinished được gọi trên sự kiện onload.

Đối với hầu hết các tập lệnh, ý tưởng ở đây là đợi cho đến khi "điều gì đó" được thực hiện hoặc đúng. Tôi rất khuyên bạn nên thử nghiệm waitfor.js. Nó thực sự quan trọng để hiểu ví dụ này trong PhantomJs.

Tôi cho rằng ví dụ của bạn là một ví dụ, nhưng hãy để tôi đề xuất câu trả lời.

Html Trang

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

Về cơ bản, waitFor sẽ kiểm tra mỗi 500 ms nếu cơ thể có một lớp có tên 'promise-executed'.

+0

Cảm ơn bạn đã trả lời chi tiết .. Tôi sẽ phải đọc thêm một chút trước khi kết hợp vào các bài kiểm tra của tôi, nhưng điều này có vẻ hợp lý và được ghi lại đầy đủ .. –

+0

có, điều này phù hợp với tôi. Hy vọng điều này sẽ giúp bạn quá. – Cybermaxs

Các vấn đề liên quan