For anybody having scope issues with GM_xmlhttpRequest
|
|
I'm sure quite a few of us have come across the issue of not being able to easily pass variables to time-delayed functions, such as GM_xmlhttpRequest or setTimeout. Especially if these functions are run inside of a recurring function, or inside a loop. So I've created an object class you can use with these functions:
function Scope(o) {
var scope = this;
for (a in o)
this[a] = o[a];
this.callback = function(r) {scope.func.call(scope, r);};
}
This simple class saved me from a lot of headaches with incorrect values. To use it, simply follow the example below:
// you may use as many variables as you'd like, but `func' MUST be set to your callback function
var scope = new Scope({myVar:some_variable, func:myCallback});
GM_xmlhttpRequest({
method:'GET',
url:'http://www.somewhere.com/something.xml',
onload:scope.callback
});
function myCallback(request) {
alert(this.myVar); // variables from the Scope object are now found in the `this' object
...
}
This works because the variables are copied to the object, thus retaining their current values. And the object will never lose scope as long as the callback function is referenced by the GM_xmlhttpRequest handler. Enjoy! |
|
|
That's useful. Also see http://userscripts.org/forums/1/topics/138#post..., though the above is perhaps the tidier solution. I still need to read up on closures/binding in JS. |
|
|
A great resource on the theory and practice of lexical closures and partial application is Brockman's Object-Oriented Event Listening through Partial Application in JavaScript. The title sets out to solve the same kind of issue under another set of circumstances (event listeners), but the solution and all understanding of the problem applies to those circumstances and yours alike. You'll have this problem in many similar situations until you understand how closures work in javascript, and then be rid of the issue. Another elegant solution proposed there is turning your recipe into
This also allows you to pass additional function arguments to myCallback, bound in before the request argument, if you'd like to, perhaps like this:
|
|
|
Johan, that solution is wonderful, as I did notice the potential conflict involving event listeners with my method. That way should work quite well under most circumstances. |
|
|
bump for relevance... another option is
while(foo){
request(a, b);
}
function request(a, b){
GM_xmlhttpRequest({
method:'GET',
url:"http://...",
onload: doIt(a,b)
});
}
function doIt(a,b){
//...
}
|
