我下载了一个名为jsdeferred
的库,试图帮助我解决一些代码流问题,但我有点迷失,因为它的示例和... 'documentation'是有些事情有点不清楚。但是当我不停地阅读和挖掘,当然还有在阳光下搜索一切时,我也发现jQuery有自己的Deferred()
系统。我正在这里联系,以获得适当的背景。
我需要找到一种方法来告诉页面“坚持到最后一件事情完成”。
这是想法 jsdeffered
所做的。所以我的问题的一部分是在问我应该使用哪个? jsDeferred或jQuery.Deferred(); 然后如何使用,如下所述。
我的情况就是这样,简而言之,我需要执行以下行为。
view model
已定义这是使用kendo ui mvvm
来声明我的视图模型,因此它是kendo.data.ObservableObject
$.ajax
调用以获取一些默认模型数据这是我遇到的最麻烦的地方。在完成$.ajax
之前,我需要一切“坚持”。但是如果我能帮助的话,我不想把所有内容都包在$.ajax().done(r)
中。这看起来/感觉非常草率,有时令人困惑。
kendo ui Remote DataSource
完成各自的数据库查询。这些实际上是按预期工作的。
jQuery Validate
已连接到视图,默认设置已经设置。这也是按预期工作的。
kendo.bind('body', viewModel);
来执行模型绑定。现在这是我遇到麻烦的地方,回到step 2
我正在进行$.ajax
通话。持续发生的事情是kendo.bind
在$.ajax
完成之前被触发。我可以将它放在$.ajax({}).done();
函数中,并且对于这个确切的一个特定页面确实有效,但是还有许多其他情况不合适。
首先,我会清楚jsdeferred
文档对我来说非常不清楚,因为逐字运行其样本实际上并不起作用。我不断被告知next is not defined
之类的。我最终发现,在您第一次致电Deferred.
之前,您必须有一个隐含的next
。
所以这就是我想到会发生的事情......
var viewModel = new kendo.data.ObservableObject({
// various view model properties defined
});
Deferred.define();
next(function() { // let's call this STEP 1
$.ajax({
// data for ajax to controller
}).done(function(result) {
// perform operations with result
});
}).
next(function() { // let's call this STEP 2
$('#dropdownlist_target').kendoDropDownList({
// parameters, remote data source for drop down list, etc.
}).data("kendoDropDownList");
}).
next(function() { // let's call this STEP 3
$('form').validate({
// any extra form validation stuff
});
}).
next(function(){ // let's call this STEP 4
kendo.bind('body', viewModel);
});
我相信,当前一个完成时,这些将一个接一个地运行。但那是不正在发生的事情。在STEP 1
和STEP 2, 3
正在运行时,4
仍处于抓取过程中。
这似乎与没有jsdeferred
库的代码运行方式有任何不同。所以我很困惑,绝对会喜欢这里的一些帮助。我需要STEP 1
才能在STEP 2
点火之前完全完成。
答案 0 :(得分:2)
问题在于next()
希望您返回您想要等待的 thing 。在第一步中,您没有返回任何内容。因此jsdeferred
假设您正在执行同步操作(已经完成),因此它继续执行步骤2.
相反,请返回jQuery.Deferred()
来电中返回的$.ajax()
。然后,jsdeferred将等待在执行步骤2之前完成。
无论如何,我都要转储jsdeferred
。正如您所知,jQuery具有完全成熟的延迟实现。我不确定jsdeferred会给派对带来什么。
使用$.ajax().done(r)
并非草率。异步行为是事件驱动语言的核心,JavaScript就是其中之一。拥抱它,或者你在生命的早期试图避免它 。
如果您还原为jQuery的延迟实现,您可能希望then()
为您提供next()
的语义;
$.ajax({
// data for ajax to controller
}).done(function(result) {
// perform operations with result
}).then(function () {
$('#dropdownlist_target').kendoDropDownList({
// parameters, remote data source for drop down list, etc.
}).data("kendoDropDownList");
$('form').validate({
// any extra form validation stuff
});
kendo.bind('body', viewModel);
}).then(function () {
// Note you can chain then()'s as well.
});
答案 1 :(得分:1)
您可以在then
结果上使用$.ajax()
方法,就像使用jsDeferred的next
帮助器一样。一般来说,then
是一种比done
更灵活的方法。正如Matt在他的回答中指出的那样,在基于承诺的编程中忘记return
处理程序中的新承诺是一个常见错误,导致它过早地使用undefined
解决,而不是等待新的承诺。
$.ajax({ // let's call this STEP 1
// data for ajax to controller
}).
then(function(result) {
// perform operations with result
}).
then(function() { // let's call this STEP 2
$('#dropdownlist_target').kendoDropDownList({
// parameters, remote data source for drop down list, etc.
}).data("kendoDropDownList");
}).
then(function() { // let's call this STEP 3
$('form').validate({
// any extra form validation stuff
});
}).
done(function(){ // let's call this STEP 4
kendo.bind('body', viewModel);
});
请注意,在我的重构中,所有这些then
将立即执行,除非返回新的promise。所以你也可以将它们结合起来。
then
接受一个返回值或promise的函数,并返回一个新的promise。如果其函数返回一个值,则会立即使用该值解析新的promise。如果它的函数返回了一个promise,那么该promise将作为新的promise传递。请注意,jQuery的then
仅适用于jQuery版本> = 1.8。