gpt4 book ai didi

javascript - 更改事件中的全局变量无法正常工作

转载 作者:行者123 更新时间:2023-12-03 06:07:53 27 4
gpt4 key购买 nike

我有纯 js 代码,其中事件处理程序更改全局变量而不将其传入。

"use strict";
var outsideEventString ="hello";
console.log("before event " + outsideEventString);

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

/*
Assume a and b are outside your control,
but you still need to set the outsideEventString arg
*/
myEmitter.on('event', function(a, b) {
console.log(a, b, this);
console.log("inside event " + outsideEventString);
outsideEventString="goodbye";
});
myEmitter.emit('event', 'a', 'b');

// this prints out goodbye which is set in the handler only
console.log("after event " + outsideEventString);

onDOMContentLoaded 事件和处理程序添加到 phantomjs 示例 netlog.js 后,代码如下所示:

"use strict";
console.log("netlog.js");
var page = require('webpage').create(),
system = require('system'),
address;

var valueString = "hello";
var value1 = {
current: false,
timeStamp: null
};
if (system.args.length === 1) {
//console.log('Usage: phantomjs netlog.js <some URL>');
phantom.exit(1);
} else {
var PHANTOM_FUNCTION_PREFIX = '/* PHANTOM_FUNCTION */';
address = system.args[1];
page.onConsoleMessage = function(msg) {
if (msg.indexOf(PHANTOM_FUNCTION_PREFIX) === 0) {
eval('(' + msg + ')()');
} else {
console.log(msg);
}
};
page.onInitialized = function() {
// add handler & apply value1 to handler's scope'
page.evaluate(function(domContentLoaded) {
document.addEventListener('DOMContentLoaded', domContentLoaded, false);
}, page.onDOMContentLoaded.apply(this, value1));
};
// handler has access to value1 and valueString
page.onDOMContentLoaded = function(event) {
value1.current = true;
value1.timeStamp = Date.now();
valueString="goodbye";
console.log('**** DOM CONTENT LOADED ****');
};
page.onResourceReceived = function (res) {
console.log('received ' + res.id + ' ' + res.stage);
};
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
//console.log(' ', item.file, ':', item.line);
});
};
page.open(address, function (status) {
console.log("page opened");
if (status !== 'success') {
console.log('FAIL to load the address');
}
console.log("value = " + JSON.stringify(value1));
console.log("valueString=" + valueString);
phantom.exit();
});
}

在代码中,valueString 是“再见”,即使它不是通过 .apply(this,value1) 传入的。

输出显示:

netlog.js
received 1 start
received 1 end
received 2 end
received 3 start
received 3 end
**** DOM CONTENT LOADED ****
received 5 start
received 5 end
received 6 start
received 6 end
received 7 start
received 9 start
received 8 start
received 7 end
received 9 end
received 8 end
received 4 start
received 4 end
page opened
value = {"current":true,"timeStamp":1473693805039}
valueString=goodbye
**** DOM CONTENT LOADED ****
**** DOM CONTENT LOADED ****

valueString 变量设置在收到 id 3 的正确 url 处,并且它会粘住,以便我可以在 page.open 中看到它。

为什么在 page.open 之后打印“**** DOM CONTENT LOADED ****”?

但是,如果我将 page.onInitialized 更改为以下内容,而不应用,则 value1valueString 都不会被设置。

page.onInitialized = function() {
// add handler & apply value1 to handler's scope'
page.evaluate(function(domContentLoaded) {
document.addEventListener('DOMContentLoaded', domContentLoaded, false);
}, page.onDOMContentLoaded);
};

为什么我需要使用 apply 方法来获取要在处理程序内设置的全局变量?

为什么我只需将 value1 传递给 apply 即可设置 valueString

最佳答案

page.evaluate 是 PhantomJS 中页面上下文的大门。只能传入原始对象。来自docs :

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!

因此,page.onDOMContentLoaded 是一个函数,不能传递到页面上下文中。您必须将对象传递到页面上下文并在那里定义一个函数。

您可以使用类似的内容(使用 the onCallback & callPhantom pair ):

page.onCallback = function(data){
if (data.type == 'DOMContentLoaded') {
console.log('outer: DOMContentLoaded');
}
};
page.onInitialized = function() {
page.evaluate(function(value1) {
// TODO: do something with value1
document.addEventListener('DOMContentLoaded', function(){
console.log('inner: DOMContentLoaded');
window.callPhantom({ type: 'DOMContentLoaded' });
}, false);
}, value1);
};
<小时/>

Why does '**** DOM CONTENT LOADED ****' print after the page.open?

请记住,Function.prototype.apply 会立即执行函数。在本例中,它是 page.onInitialized 内部的 page.onDOMContentLoaded 函数。因此,每当页面“初始化”时,您都会看到 page.onDOMContentLoaded 的执行结果。

为什么执行停止后会初始化两个页面是一个完全不同的问题。这可能只是 PhantomJS 的一些特性。

关于javascript - 更改事件中的全局变量无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39453981/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com