使用phantomjs-node实现waitFor功能 [英] Implementing waitFor functionality with phantomjs-node

查看:44
本文介绍了使用phantomjs-node实现waitFor功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试并测试了 - 成功 - 幻影示例 waitFor 。但是,我很难通过 phantomjs-node 模块实现它,主要是因为 page.evaluate 在回调中得到评估。

I have tried and tested - with success - the phantomjs example waitFor. However, I am having difficulty implementing it via the phantomjs-node module primarily because page.evaluate gets evaluated in a callback.

PhantomJS 实施

page.open("http://twitter.com/#!/sencha", function () {
    waitFor(function() {

        // This here is easy to do as the evaluate method returns immediately
        return page.evaluate(function() {
            return $("#signin-dropdown").is(":visible");
        });

    }, function() {
       console.log("The sign-in dialog should be visible now.");
       phantom.exit();
    });
  }
});

然而,使用 phantomjs-node ,evaluate函数会返回一个返回的数据回调:

However, with phantomjs-node the evaluate function gets returned data in a callback:

page.evaluate(
    function(){ /* return thing */ },
    function callback(thing) {  /* write code for thing */ }
)

使用 phantomjs-node ,如何在元素可见后才能在页面上运行函数?

Using phantomjs-node, how can I run a function on the page only after an element is visible?

如果上面的链接已经死了,这里是waitFor函数的实现

Just in case the link above is dead, here is the implementation of the waitFor function

/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
    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");
                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
            }
        }
    }, 250); //< repeat check every 250ms
};

提前致谢。

推荐答案

今天遇到这个问题,以为我会分享我的解决方案。

Ran into this problem today, thought I'd share my solution.

  // 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()
    }
  }

第一步是创建一个新的 wait 函数。它采用与原始 waitFor 函数相同的参数,但工作方式略有不同。在测试函数 testFx 的回调之后,我们必须递归地运行 wait 函数,而不是使用间隔。被触发了。另外,请注意,您实际上不需要传递 start 的值,因为它会自动设置。

The first step is creating a new wait function. It takes the same parameters as the original waitFor function, but works a little differently. Instead of using an interval, we have to run the wait function recursively, after the callback from the test function testFx has been triggered. Also, note that you don't actually need to pass in a value for start, as it gets set automatically.

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

在这个例子中,我正在为 testFx 设置回调用作回调 page.evaluate ,它根据是否能够在页面上找到某个元素返回true / false值。或者,您可以为 page.evaluate 创建回调,然后从中触发 testFx 回调,如下所示:

In this example, I'm setting the callback for testFx function as the callback to page.evaluate, which returns a true/false value based on whether or not it was able to find some element on the page. Alternatively, you could create your callback for page.evaluate and then trigger the testFx callback from it, as shown below:

  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

这篇关于使用phantomjs-node实现waitFor功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆