在我们的工作场所,我们在site.master页面中定义了一个脚本队列
<script>
// append functions to this array that will be executed after js dependencies have loaded
var script_queue = [];
</script>
然后我们将javascript函数推送到此script_queue来执行它们。我遇到了一个问题,比如我有两个功能
<script type="text/javascript">
// THIS IS FUNCTION 1
script_queue.push(function() {
// set the width of the thumbnail list to the sum of all the li widths
var thumbsWidth = 0;
$('#oneClipPlaylist li').each(func
…
}
</script>
script_queue.push(function() {
// THIS IS FUNCTION 2
var allInputs = $('fieldset.categories input');
var categoryInputs = $('fieldset.categories input').not('#categoryAll');
var categoryAllInput = $('#categoryAll');
allInputs.click(function() {
var checkbox = $(this);
这是队列的处理方式:
<script>
(function () {
for (var i in script_queue) {
script_queue[i]();
}
} ());
</script>
如何确保在功能2之前执行功能1?因为我遇到了我的功能2在功能1之前执行并且结果不正确的问题
答案 0 :(得分:1)
我很久以前就已经实现了类似的系统,远在很远的地方工作:) 我们的目的是在需要这些依赖项的其他脚本之前加载依赖项。例如,如果您以这种方式加载jQuery,那么使用jQuery的任何其他脚本显然必须在加载jQuery之后才执行。任何自定义JS对象都是如此。
一些注意事项:
你的代码将在for循环中以正确的顺序执行。所以,如果没有发生,那么它应该是
如何向队列添加功能。它们可能不会按照您的想法添加。这将是一个原因;
使用Ajax回调或其他异步代码的函数,例如动态加载外部JS文件。函数可能会执行并等待结果,但在等待时,其他函数将在for循环中执行。
第一个很容易检查 - 只需在处理函数之前验证函数的顺序是否正常,然后查看它是否按正确的顺序排列,然后检查应用程序代码以了解发生这种情况的原因。
最有可能的是,这是由于#2 - 异步调用加载JS文件和/或Ajax调用; (要查看如何/为什么它不按顺序工作的示例,请参阅答案的底部)
一种可能的解决方案:各种脚本加载管理器
相当简单,我们使用此对象将脚本添加到队列中,特别考虑了Ajax。脚本可以全部依赖于任何内容或其他脚本。当我们处理队列时,只会立即执行没有依赖关系的脚本。
然后,当脚本完成时,将执行任何相关脚本。唯一特殊情况是Ajax,只需要进行微小的更改,即向context
个settings
调用的jQuery.ajax()
对象添加jQuery.ajaxComplete()
属性,并注册全局context
。 <script type="text/javascript">
// Let's create global $jsload object to handle queueing of JS scripts
var $jsload = (function () {
// Let's make the internals private
var scriptQueue = {};
var dependencies = {};
var enqueue = function (key, scriptFunc, dependencyKey, isAjax) {
scriptQueue[key] = {
dependencyKey: dependencyKey,
func: function () {
scriptFunc();
if (!isAjax) scriptCallBack(key);
}
};
addDependencyItem(key, dependencyKey);
}
var addDependencyItem = function (key, dependencyKey) {
if (null == dependencyKey) return;
// Check to add to dependencies
if (null == dependencies[dependencyKey] || 'undefined' == dependencies[dependencyKey])
dependencies[dependencyKey] = {};
// add this script to dependent scripts
dependencies[dependencyKey][key] = { isCompleted: false };
};
var checkDependency = function (key, dependencyKey) {
var obj = dependencies[scriptQueue[key].dependencyKey];
if (null != obj && !obj.isCompleted)
return false;
return true;
};
var scriptCallBack = function (key) {
// Called when a script has finished; now ok to process dependencies
if (null != dependencies[key]) {
for (var itemKey in dependencies[key]) {
scriptQueue[itemKey].func();
dependencies[key][itemKey].isCompleted = true;
}
}
};
// The jsLoaderWithDependency object executes dependent scripts in the correct order
// The only callable public methods are queue, ajax, and processQueue
var jsLoaderWithDependency = {
queue: function (key, scriptFunc, dependencyKey) {
enqueue(key, scriptFunc, dependencyKey, false)
},
ajax: function (key, scriptFunc, dependencyKey) {
enqueue(key, scriptFunc, dependencyKey, true)
},
processQueue: function () {
for (var key in scriptQueue) {
if (checkDependency(key)) {
scriptQueue[key].func();
}
}
}
}
// This handler will execute at end of all Ajax requests;
// You can instead meake separate success/error handlers,
// for example, not to execute dependency scripts on error
// yet still show a message and/or log the error, etc.
$(document).ready(function () {
$(document).ajaxComplete(function (event, xhr, settings) {
scriptCallBack(settings.context);
});
});
return jsLoaderWithDependency;
})(); // Auto-execute self and init
</script>
属性的值应设置为脚本键(即“Script0”)。
$ jsload对象:
<script type="text/javascript">
// Usage and test code
$jsload.ajax(
"Script0",
function () {
$.ajax({
// This is the only small change needed for dependency callback
context: "Script0",
// Standard ajax settings
url: "",
data: "ho ho ho",
dataType: "jsonp",
jsonp: "jsonp",
success: function (response, textS, xhr) {
console.log("Script 0 ( Ajax ) (no dependency) success");
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
console.log("Script 0 ( Ajax ) (no dependency) error");
}
});
console.log("Script 0 ( Ajax ) (no dependency) start");
},
null
);
$jsload.queue(
"Script1",
function () { console.log("Script 1 (dependency on Script 0, ajax callback)"); },
"Script0"
);
$jsload.queue(
"Script2",
function () { console.log("Script 2 (depends on Script 3)"); },
"Script3"
);
$jsload.queue(
"Script3",
function () { setTimeout(console.log("Script 3 Timeout (depends on Script 1)"), 1000); },
"Script1"
);
$jsload.queue(
"Script4",
function () { console.log("Script 4 (no dependency)");},
null
);
$jsload.processQueue();
</script>
如何排队和执行功能的一些使用示例:
// Adding basic functions to queue
script_queue.push(function () { console.log(1); });
script_queue.push(function () { console.log(2); });
script_queue.push(function () { console.log(3); });
script_queue.push(function () { console.log(4); });
script_queue.push(function () { console.log(5); });
// Let's do some Ajax!
script_queue.push(function () {
$.ajax({
type: "GET", url: "http://otherdomain.com/somePage.html",
data: "ho ho ho", dataType: "jsonp", jsonp: "jsonp",
success: function (response, textS, xhr) {
console.log("6 ajax finished success")
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
console.log("6 ajax finished error")
}
});
console.log("6 ajax start");
});
// Let's throw in a timeout
script_queue.push(function () {
window.setTimeout(function () { console.log("7 with timeout") }, 1000);
});
script_queue.push(function () { console.log(8); });
script_queue.push(function () { console.log(9); });
script_queue.push(function () { console.log(10); });
// Process the funcs
(function () {
for (var i in script_queue) {
script_queue[i]();
}
} ());
</script>
结果:
这实际上是一个基本的开始,当然可以改进它来处理动态脚本加载(使用加载的事件)和其他应用程序需求。但我认为这对于这种功能的框架来说是一个不错的开端。
没有依赖关系的基本代码示例及其中断的一些场景:
这是一个简单的脚本处理示例,除了超时和异步调用: //将函数附加到此数组,该数组将在加载js依赖项后执行 var script_queue = [];
{{1}}
并且,控制台的结果:
正如您所看到的,大多数函数按顺序执行 - Ajax以正确的顺序启动 - 但是当执行回调并且超时完成时,所有其他函数都已经处理完毕。
希望这会有所帮助,并为您提供一些想法!
答案 1 :(得分:0)
命名第二个函数并且不将其排队,然后在第一个放入队列的函数的末尾调用第二个函数。
<script type="text/javascript">
// THIS IS FUNCTION 1
script_queue.push(function() {
// set the width of the thumbnail list to the sum of all the li widths
var thumbsWidth = 0;
$('#oneClipPlaylist li').each(func
…
secondFunc();
}
function secondFunc() {
// THIS IS FUNCTION 2
var allInputs = $('fieldset.categories input');
var categoryInputs = $('fieldset.categories input').not('#categoryAll');
var categoryAllInput = $('#categoryAll');
allInputs.click(function() {
var checkbox = $(this);
...
}
</script>