Javascript 使用phantomjs节点实现waitFor功能

Javascript 使用phantomjs节点实现waitFor功能,javascript,node.js,phantomjs,Javascript,Node.js,Phantomjs,我已经尝试并测试了phantomjs示例,并取得了成功。但是,我很难通过模块实现它,主要是因为page.evaluate在回调中进行计算 PhantomJS实现 page.open(“http://twitter.com/#!/sencha“,函数(){ waitFor(函数(){ //这很容易做到,因为evaluate方法会立即返回 返回page.evaluate(函数(){ 返回$(“#登录下拉列表”)。为(“:可见”); }); },函数(){ log(“登录对话框现在应该是可见的。”);

我已经尝试并测试了phantomjs示例,并取得了成功。但是,我很难通过模块实现它,主要是因为
page.evaluate
在回调中进行计算

PhantomJS实现

page.open(“http://twitter.com/#!/sencha“,函数(){
waitFor(函数(){
//这很容易做到,因为evaluate方法会立即返回
返回page.evaluate(函数(){
返回$(“#登录下拉列表”)。为(“:可见”);
});
},函数(){
log(“登录对话框现在应该是可见的。”);
phantom.exit();
});
}
});
但是,使用phantomjs节点,evaluate函数在回调中获取返回的数据:

page.evaluate(
函数(){/*返回对象*/},
函数回调(thing){/*为thing编写代码*/}
)
使用phantomjs节点,如何仅在元素可见后才能在页面上运行函数

为了防止上面的链接失效,下面是waitFor函数的实现

/**
*等待测试条件为真或出现超时。等待有用
*在服务器响应或发生ui更改(fadeIn等)时。
*
*@param testFx计算为布尔值的javascript条件,
*它可以作为字符串传入(例如:“1==1”或“$”(“#bar”)。is(“:visible”)”或
*作为回调函数。
*@param onReady满足testFx条件时该怎么办,
*它可以作为字符串传入(例如:“1==1”或“$”(“#bar”)。is(“:visible”)”或
*作为回调函数。
*@param timeOutMillis是等待的最大时间。如果未指定,则使用3秒。
*/
函数waitFor(testFx、onReady、timeOutMillis){
var maxtimeOutMillis=timeOutMillis?timeOutMillis:3000,//<默认最大超时为3s
开始=新日期().getTime(),
条件=假,
间隔=设置间隔(函数(){
如果((新日期().getTime()-start

提前感谢。

我已经为called编写了一个替代方法。它没有将所有函数调用和赋值转换为异步操作,而是在PhantomJS中执行整个函数

我认为你的问题可以这样解决:

phridge.spawn()
    .then(function (phantom) {
        return phantom.openPage(url);
    })
    .then(function (page) {
        return page.run(selector, function (selector, resolve, reject) {
            // this function runs inside PhantomJS bound to the webpage instance
            var page = this;
            var intervalId = setInterval(function () {
                var hasBeenFound = page.evaluate(function (selector) {
                    return Boolean(document.querySelector(selector));
                }, selector);

                if (hasBeenFound === false &&
                    /* check if there is still some time left  */) {
                    // wait for next interval
                    return;
                }

                clearInterval(intervalId);

                if (hasBeenFound) {
                    resolve();
                } else {
                    reject(new Error("Wait for " + selector + " timeout"));
                }
            }, 100);
        });
    })
    .then(function () {
        // element has been found
    })
    .catch(function (err) {
        // element has not been found
    });

今天遇到这个问题,我想和大家分享我的解决方案

  // custom helper function
  function wait(testFx, onReady, maxWait, start) {
    var start = start || new Date().getTime()
    if (new Date().getTime() - start < maxWait) {
      testFx(function(result) {
        if (result) {
          onReady()
        } else {
          setTimeout(function() {
            wait(testFx, onReady, maxWait, start)
          }, 250)
        }
      })
    } else {
      console.error('page timed out')
      ph.exit()
    }
  }
在本例中,我将
testFx
函数的回调设置为对
页面的回调。evaluate
,它根据是否能够在页面上找到某些元素返回真/假值。或者,您可以为
页面创建回调。evaluate
然后触发
testFx
校准从它返回,如下所示:

  wait(function (cb) {
    return page.evaluate(function () 
      // check if something is on the page (should return true/false)
      return something
    }, function(result) {
      var newResult = doSomethingCrazy(result)
      cb(newResult)
    }
  }, function () { // onReady function
    // code
  }, 5000) // maxWait

我最近创建了一个相当简单的节点模块,将waitFor移植到节点:

var async=require('async');
module.exports=waitFor;
/**
*waitFor用于的端口
*@见{@linkhttps://github.com/ariya/phantomjs/blob/master/examples/waitfor.js}
*@见{@linkhttps://github.com/sgentle/phantomjs-node}
*@callback testFx-Test函数将重复,直到达到true或超时限制
*@callback onReady-在“testFx”通过时触发。
*@param{(number | boolean | string)}[timeOut=false]-如果定义为false或字符串值为`forever`
*然后,“waitFor”将一直运行,直到“testFx”通过
*超时,否则以毫秒为单位传递一个数字。
*/
函数waitFor(testFx、onReady、超时){
var maxtimeOutMillis=typeof timeOut!=“未定义”?超时:5000//如果未定义,默认最大超时为5s
,start=new Date().getTime()
,isAsync=testFx.length>0
,通过=未定义
;
异步。直到(
函数测试(){
返回传递类型!==“未定义”;
},
功能动作(cb){
setTimeout(函数(){
如果(!maxtimeOutMillis | | maxtimeOutMillis=='forever'| | new Date().getTime()-start
如何使用
phridge
生成PDF?与普通的幻影没有区别
  wait(function (cb) {
    return page.evaluate(function () 
      // check if something is on the page (should return true/false)
      return something
    }, function(result) {
      var newResult = doSomethingCrazy(result)
      cb(newResult)
    }
  }, function () { // onReady function
    // code
  }, 5000) // maxWait
var async = require('async');

module.exports = waitFor;

/**
 * waitFor port used with 
 * @see    {@link https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js}
 * @see    {@link https://github.com/sgentle/phantomjs-node}
 * @callback testFx - Test function, will repeat until true or timeout limit is reached
 * @callback onReady - Fires if/when `testFx` passes.
 * @param {(number|boolean|string)} [timeOut=false] - If defined and falsey or string value of`forever` 
 *                                                    then `waitFor` will run until `testFx` passes without 
 *                                                    timing out, otherwise pass a number in miliseconds.
 */
function waitFor(testFx, onReady, timeOut) {

    var maxtimeOutMillis = typeof timeOut !== 'undefined' ? timeOut : 5000 // Default Max Timout is 5s if not defined
        , start = new Date().getTime()
        , isAsync = testFx.length > 0
        , passing = undefined
    ;

    async.until(
        function Test() { 
            return typeof passing !== 'undefined'; 
        },
        function Action(cb) {
            setTimeout(function(){

                if (!maxtimeOutMillis || maxtimeOutMillis == 'forever' || new Date().getTime() - start < maxtimeOutMillis) {

                    // If a callback is passed to `testFx` we'll handle that.
                    function useCallback(){
                        passing = arguments[0]
                        return cb();
                    };                    

                    passing = (function(){
                        return (typeof(testFx) === "string" ? eval(testFx) : testFx).apply(this, arguments);
                    })(isAsync ? useCallback : undefined);

                    if(!isAsync) cb();

                } else {
                    return cb(new Error('`waitFor` timeout'));
                }

            }, 250);
        },
        function Done(err) {
            return (function(){
                return (typeof(onReady) === "string" ? eval(onReady) : onReady).apply(this, arguments);                  
            })(err, passing);
        }
    );

}