admin管理员组文章数量:1405339
I have the following script which does not work properly:
function getWidgetContent( widget ) {
if(widget.script!=null){
$global_widget_id = widget.widget_id;
$.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
});
}
}
This is called as follows:
for ( j = 0; j <= widget_data.d.length - 1; j++ ) {
getWidgetContent( widget_data.d[j] );
}
I thought this would run the function, within the function, assign a value to the global value, then run the $.getScript
per iteration of the loop. But that is not happening. It seems to iterate through the loop until the loop is finished, lets say it loops 3 times, assign a value to the global value each time, i.e. 3 times, and then it finally goes and does the $.getScript
.
Ofcourse that will not working as it will now only use the last assignment of the global value in the $.getScript file 3 times...
How do I change this so it assigns a value to the global variable, runs the $.getScript
. When done, continue with the original loop, assign the next value to the global variable, run the $.getScript
until the loop has finished.
I have the following script which does not work properly:
function getWidgetContent( widget ) {
if(widget.script!=null){
$global_widget_id = widget.widget_id;
$.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
});
}
}
This is called as follows:
for ( j = 0; j <= widget_data.d.length - 1; j++ ) {
getWidgetContent( widget_data.d[j] );
}
I thought this would run the function, within the function, assign a value to the global value, then run the $.getScript
per iteration of the loop. But that is not happening. It seems to iterate through the loop until the loop is finished, lets say it loops 3 times, assign a value to the global value each time, i.e. 3 times, and then it finally goes and does the $.getScript
.
Ofcourse that will not working as it will now only use the last assignment of the global value in the $.getScript file 3 times...
How do I change this so it assigns a value to the global variable, runs the $.getScript
. When done, continue with the original loop, assign the next value to the global variable, run the $.getScript
until the loop has finished.
- Updated question as I have realised why the problem is happening. – oshirowanen Commented Dec 7, 2012 at 12:22
- Can you provide a live demo, or at least give us more info on what the script is supposed to be doing? Is the script checking / relying on the widget_id? That's clearly the problem. If at all possible, you should use getscript once with a generic function, and then call that function 3 times with each widget. Or, you could pass the widget_id as a GET param, and have some PHP serve the javascript file. Lastly, if you absolutely need to load 3 times, refactor so that j is the global variable, and the getScript success function does j++, then basically calls itself. – James S Commented Dec 17, 2012 at 1:24
7 Answers
Reset to default 1You're getting this because $.getScript is an asynchronous method. In this case, it means that the method returns immediately before the script has finished loading, and continues executing code after it.
What this means is that something like:
$.getScript('a.js', function () {
console.log('Loaded a');
});
$.getScript('b.js', function () {
console.log('Loaded b');
});
$.getScript('c.js', function () {
console.log('Loaded c');
});
// Output could be:
// Loaded c
// Loaded a
// Loaded b
This means that all of the script files requests can be done simultaneously but it also means that the order is not deterministic (fixed).
Use Promises
You can ensure that the getWidgetContent
is called sequentially by chaining promises if you are using jQuery 1.5 and above.
However, the pitfall of this method is that you will not be concurrently loading all the script requests at the same time, the requests will be sent one after another after the previous one has pleted.
Make sure you return the result of $.getScript which is a Deferred Object (I made minimal changes here, just note the return
statements):
function getWidgetContent( widget ) {
if(widget.script!=null){
$global_widget_id = widget.widget_id;
return $.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
});
}
return null;
}
New method to perform a new getWidgetContent after a previous promise is fulfilled (pletion of previous action):
function doGetWidgetContentAfter(promise, widget) {
return promise.then(function () {
return getWidgetContent( widget );
});
}
Calling it:
var promise = $.when(true);
for ( j = 0; j <= widget_data.d.length - 1; j++ ) {
promise = doGetWidgetContentAfter( promise, widget_data.d[j] );
}
Explanation
What doGetWidgetContentAfter
does is that when the said promise
is plete then call the getWidgetContent
function for widget
. The then
method returns a promise that pletes when any internal methods promise pletes.
I know it's starting to sound plicated, but do play around and experiment with it. :)
Looking the others answers I can only think in do. Change the your implementation:
$.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
});
To a corresponding ajax call, but not asynchronous
$.ajax({
url: "js/" + widget.script,
dataType: "script",
async: false,
success: function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
}
});
getWidgetContent
is doing the getScript
, but getScript
returns immediately instead of waiting for the network (which is relatively slow pared to the CPU) to finish getting your script. This is not a bug, but an awesome thing - with asynchronous programming, you can get lots of work done on the CPU, and you don't have to wait for things that are much slower than the CPU if you don't want to!
To answer your question:
- To set the global variable when the script request is done, simply move the variable assignment into your callback function.
- Simply allowing all
getScripts
to run at once would be faster, but if you really can't allow a secondgetScript
to start until the first finishes, callgetWidgetContent
just once, and have your callback determine the next widget in line and callgetWidgetContent
again with it.
the getScript method is async, so before you get a response from the server containing youre script value the loop runs the next iteration
thats why we have to send in a callback function. javascript knows what to do once the server responds. so while a normal loop cant help us here we can use a recusive function.
what happens is thatwe get the callback function to call the loopFunc that then moves on to the next item in the collection/array.
i hoppe this can give you som inspriation:
var getWidgetContent = function(wiget, loopFunc) {
if(widget.script!=null){
$global_widget_id = widget.widget_id
$.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title )
loopFunc() //now we got a response from the server and want to move on to the next script tag.
})
}
}
var i = 0
(function loopFunc(){ //we define a function and call it instantly
if(i < widget_data.d.length){
getWidgetContent(widget_data.d,loopFunc) //now we call the getWidgetContent but we send in the current function aswell
console.log($global_widget_id) // this is going to change each time
i += 1
}
}())
Try assigning the variable to the window namespace:
window.global_widget_id = "foo";
You can then reference it like this:
var myId = window.global_widget_id;
and overwrite it:
window.global_widget_id = "newId";
(The (Incorrect. Ignore that last part.)$
in your variable assignment might be confusing jQuery too.)
EDIT:
It appears $.getScript()
files aren't part of the global scope: jQuery's getScript - including files into the main scope?.
Maybe you could call the $.getScript()
functions from a callback rather than an embedded document.ready()
, and pass the variable through that way?
May be it can help you, Placing function inside loops can rewrite variable that contained in it
In my opinion, do it like this:
function getWidgetContent(widget) {
if(w_script != null){
// And make variable for make sure each values e
// from parent function and not from `$.getScript`
var w_script = widget.script;
var w_widget_id = widget.widget_id;
var w_title = widget.title;
$.getScript( "js/" + w_script, function() {
$( ".widget_header_title_" + w_widget_id ).append( w_title );
});
}
}
This case have face me, but i face it on $.ajax
, and i try to make variable like above
Call me if success, good luck
If you wan't the code to be executed in order then you will have to rewrite it a bit. The next call to getScript
should not be done until the previous one has called its callback. This can be done by calling getWidgetContent
from the callback...
Something like:
function getWidgetContent(d, index) {
var widget = d[index];
if(widget.script!=null){
$global_widget_id = widget.widget_id;
$.getScript( "js/" + widget.script, function() {
$( ".widget_header_title_" + widget.widget_id ).append( widget.title );
if (index <= d.length - 1)
getWidgetContent(d,index+1); //call the next one
});
}
}
//Start the calls
getWidgetContent( widget_data.d,0);
本文标签: javascriptHaving difficulty working with global variables and getScriptStack Overflow
版权声明:本文标题:javascript - Having difficulty working with global variables and $.getScript - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744883048a2630321.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论