首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将参数传递给page.includeJs()和page.evaluate()中的匿名函数

将参数传递给page.includeJs()和page.evaluate()中的匿名函数
EN

Stack Overflow用户
提问于 2012-09-01 05:45:43
回答 1查看 8.9K关注 0票数 17

一点背景..。我对javascript和phantom.js都是个新手,所以我不知道这是javascript还是phantom.js bug (特性?)。

下面的代码成功完成(很抱歉,缺少phantom.exit(),一旦完成,您就必须使用ctrl+c ):

代码语言:javascript
复制
var page = require('webpage').create();
var comment = "Hello World";

page.viewportSize = { width: 800, height: 600 };
page.open("http://www.google.com", function (status) { 
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
            console.log("1: ", comment);
        }, comment);

        var foo = page.evaluate(function() {            
            return arguments[0];
        }, comment);

        console.log("2: ", foo);            
    }
});

这是可行的:

代码语言:javascript
复制
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
    console.log("1: ", comment);
}, comment);

输出1: Hello World

但不是:

代码语言:javascript
复制
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function(c) {
    console.log("1: ", c);
}, comment);

输出1: http://code.jquery.com/jquery-latest.min.js

而不是:

代码语言:javascript
复制
page.includeJs('http://code.jquery.com/jquery-latest.min.js', function() {
    console.log("1: ", arguments[0]);
}, comment);

输出1: http://code.jquery.com/jquery-latest.min.js

看第二部分,这是可行的:

代码语言:javascript
复制
var foo = page.evaluate(function() {            
    return arguments[0];
}, comment);

console.log("2: ", foo);

输出2: Hello World

还有这个:

代码语言:javascript
复制
var foo = page.evaluate(function(c) {           
    return c;
}, comment);

console.log("2: ", foo);

输出2: Hello World

但不是这样的:

代码语言:javascript
复制
var foo = page.evaluate(function() {            
    return comment;
}, comment);

console.log("2: ", foo);

输出

ReferenceError:找不到变量:注释

phantomjs://webpage.valuate():2

phantomjs://webpage.valuate():3

phantomjs://webpage.valuate():3

2:空

好消息是,我知道什么是有效的,什么是无效的,但是如何保持一点一致性呢?

为什么includeJsevaluate会有不同

向匿名函数传递参数的正确方式是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-09-01 06:26:28

要理解PhantomJS的棘手之处在于有两个执行上下文-幻影上下文,它位于您的机器本地,可以访问phantom对象和required模块;远程上下文,它存在于无头浏览器的window中,只能访问您通过page.load加载的网页中加载的内容。

您编写的大部分脚本都是在Phantom上下文中执行的。主要的例外是page.evaluate(function() { ... })中的任何内容。这里的...是在被沙箱保护的远程上下文中执行的,不能访问本地上下文中的变量和对象。您可以通过以下方式在两个上下文之间移动数据:

  • 从传递给page.evaluate()的函数返回值,或者
  • 将参数传递给该函数。

这样传递的值本质上是在每个方向上序列化的-不能用方法传递复杂的对象,只能传递像字符串或数组这样的数据对象(我不知道确切的实现,但经验法则似乎是,任何可以用JSON序列化的东西都可以在这两个方向上传递)。您不能访问page.evaluate()函数之外的变量,就像使用标准Javascript一样,只能访问作为参数显式传递的变量。

那么,您的问题是:为什么includeJs和之间存在差异?

  • .includeJs(url, callback)接受一个回调函数,该函数在幻影上下文中执行,显然接收url作为其第一个参数。除了它的参数之外,它还可以访问(就像任何普通的JavaScript函数一样)其封闭作用域中的所有变量,包括示例中的comment。它在回调函数后不需要额外的参数列表--当你在回调函数中引用comment时,你引用的是一个外部变量,而不是一个函数参数。

var foo =“});

  • .evaluate(function, args*)”;page.includeJs('http://code.jquery.com/jquery-latest.min.js',console.log(){ //此回调函数在幻影上下文页面中执行(“jQuery是在远程上下文中加载的。”);//它可以访问外部作用域变量,包括“幻象”页面(foo,nowDoMoreStuff);var接受要执行的函数以及传递给它的零个或多个参数(以某种序列化形式)。您需要在函数签名中命名参数,例如function(a,b,c),或者使用arguments对象访问它们-它们不会自动与您传入的变量具有相同的名称。

var foo = "stuff";var bar =“用于远程页面的东西”;var result = page.evaluate( function (bar2) { //此函数在远程上下文中执行//它可以访问您在$(‘title’).html(Bar2)中传递的DOM、远程库和参数;//但不能访问外部作用域vars return typeof foo +“”+ typeof bar;},bar);console.log(result);// " undefined "

因此,对于不同方法中的函数,传入参数的正确方式是不同的。对于injectJs,回调将使用一组新的参数(至少包括URL)来调用,因此您想要访问的任何变量都需要在回调的封闭范围内(即您可以在函数的闭包中访问它们)。对于evaluate来说,只有一种方法可以传递参数,那就是将它们包含在传递给evaluate本身的参数中(还有其他方法,但是这些方法都很棘手,现在这个特性已经在PhantomJS中可用了,所以不值得讨论)。

票数 44
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12222856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档