【问题标题】:Phantomjs page.evaluate and q deferred issuePhantomjs page.evaluate 和 q 延迟问题
【发布时间】:2015-03-06 16:20:25
【问题描述】:

我正在尝试将“Q”承诺库与 PhantomJS 一起使用,但下面的代码不起作用。

app.evaluate_page=function(page){
    var deferred = q.defer();
    console.log("Before the page evaluation");
    page.evaluate(function(){
        deferred.resolve(page);
    });
    return deferred.promise;
};

以下是错误

Before the page evaluation
ReferenceError: Can't find variable: deferred
  phantomjs://webpage.evaluate():2
  phantomjs://webpage.evaluate():3
  phantomjs://webpage.evaluate():3

看起来它无法找到在外部范围中定义的延迟变量,这很奇怪。相同类型的代码适用于其他具有回调的方法,如 page.open 方法。

下面的代码只是按预期工作,不知道为什么上面的代码不能。

app.openPage = function(options){
  var deferred = q.defer();
  page.open(options.url,function(status){
      if(status!=="success"){
          deferred.reject(new Error("Page could not be loaded at "+ options.url ));
      }
      else {
          deferred.resolve(page);
      }
  });
  return deferred.promise;
};

【问题讨论】:

  • 你想达到什么目的? page.evaluate() 是同步的。
  • 是的。我希望 page.evaluate 是同步的。
  • 是的,那你为什么需要q
  • 哦,好的。我不确定。让我同步使用它,看看它是如何工作的。谢谢,
  • page.open 也是同步的吗?

标签: javascript phantomjs q


【解决方案1】:

page.evaluate在浏览器进程中运行,无法访问你的变量。

你有 page 同步变量,所以你不需要在这里承诺。

【讨论】:

    【解决方案2】:

    正如@slaks 所说,page.evaluate 回调函数在沙盒环境中运行。

    official documentation 明确指出page.evaluate

    在网页上下文中评估给定的函数。这 执行是沙盒的,网页无权访问幻影 对象,它无法探测自己的设置。

    但您可以传入和传出参数,但正如 official documentation 所述:

    注意:评估函数的参数和返回值必须 是一个简单的原始对象。经验法则:如果可以的话 通过JSON序列化,就可以了。

    截至目前(2016 年 10 月),深入研究该主题,这似乎是一个悬而未决的问题。

    1. github 上有一个关于使用page.evaluate 启用承诺的未解决问题:Waitfor support for Promise pattern · Issue #14166 · ariya/phantomjs
    2. 有一个实验 api 可以从网页上下文中启用回调函数:onCallback | PhantomJS
    3. 等待网页准备好的官方方法是扩展waitfor.js example

    我使用第三种方法的个人混合。

    这是我的main.js 文件:

    'use strict';
    
    var wasSuccessful = phantom.injectJs('./lib/waitFor.js');
    var page = require('webpage').create();
    
    page.open('http://foo.com', function(status) {
      if (status === 'success') {
        page.includeJs('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', function() {
          waitFor(function() {
            return page.evaluate(function() {
              if ('complete' === document.readyState) {
                return true;
              }
    
              return false;
            });
          }, function() {
            var fooText = page.evaluate(function() {
              return $('#foo').text();
            });
    
            phantom.exit();
          });
        });
      } else {
        console.log('error');
        phantom.exit(1);
      }
    });
    

    还有lib/waitFor.js 文件(它只是来自phantomjs waitfor.js examplewaifFor() 函数的复制和粘贴):

    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 condi>
                        clearInterval(interval); //< Stop this interval
                    }
                }
            }, 250); //< repeat check every 250ms
    }
    

    这个方法不是异步的,但至少我确信在我尝试使用它们之前已经加载了所有资源。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-11
      • 2013-09-27
      • 2018-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多