2014-10-03 62 views
0

我知道Ajax的本质是异步的,因此我的代码是错误的。 但我需要帮助才能找到另一种解决方案。如何使AJAX同步

案例是:我将数据插入我的数据库:

self.insertTextItem = function (item) { 
    console.log("Insert TextItem with Service"); 
    return $.ajax({  
     type: "POST", 
     url: serviceRoot + "InsertTextbatchTagItem", 
     beforeSend: serviceFramework.setModuleHeaders, 
     data: item, 
     cache: false 
    }); 
}; 

item.Id = null; // Id is autocreated in db. 
item.Text = "Finally Friday!"; 

self.insertTextItem(item)  
    .done(function (newtext) { 
       item.textbatchId = newtext.Id; 
} 

//continuous code… 

这在大多数情况下找到。 异常是我需要从数据库中立即返回的数据。 但是我需要“连续代码”来等待Id被返回。 显而易见的解决方案是将“连续代码”放入回调函数中,但实际上,我在一个函数中调用self.insertTextItem,因此调用函数无需等待即可返回。 (显然回调函数在调用函数中结束。)

如何在这种情况下重写self.insertTextItem函数?

+1

在'done()'回调中实现连续代码。 – 2014-10-03 08:56:23

+0

@Asle使ajax同步可以挂起你的应用程序。如果你希望数据在ajax调用完成时可用尝试使用回调函数 – 2014-10-03 08:58:51

+0

通常的解决方案是禁用ui,可能会显示带覆盖的ajax微调, - 在ajax回调中启用。同步ajax锁定用户界面,并造成不愉快的体验 – andrew 2014-10-03 08:59:11

回答

3

异常是我需要从数据库中立即返回的数据。不过,我需要“连续代码”来等待Id被返回。

最好的办法是不要让这种情况发生,而是要接受事件驱动的,基于浏览器和网络编程的异步性质。

非常小的选项是强制ajax请求同步。目前,在jQuery 1.x中,您可以通过将async: false添加到您的呼叫中来实现此目的;您还必须开始使用自己的$.Deferred而不是从ajax得到的那个,因为从jQuery 1.8开始,使用async: falsejqXHR的内置许诺已被弃用。所以:

self.insertTextItem = function (item, synchronous) { // <== Optional flag 
    var deferred = $.Deferred();      // <== Your own Deferred 
    console.log("Insert TextItem with Service"); 
    $.ajax({  
     type: "POST", 
     url: serviceRoot + "InsertTextbatchTagItem", 
     beforeSend: serviceFramework.setModuleHeaders, 
     data: item, 
     cache: false, 
     async: synchronous === true ? false : true, // <=== Use it, ignoring `undefined` and othe rfalsey values 
     success: function(data) {     // Handling you Deferred 
      deferred.resolveWith(data);    // (this is probably incomplete) 
     },           // 
     error: function() {       // 
      deferred.reject();      // 
     }           // 
    }); 
    return deferred.promise();      // Return the promise for your Deferred 
}; 

这将使insertTextItem块(锁定了大多数浏览器的用户界面),直至调用完成。由于jQuery的承诺的工作方式,这也将使done回调同步。 (许多其他承诺实现并非如此,但它是jQuery的。)

该选项使用XMLHttpRequest的基本功能,该功能允许同步ajax。

这个选项也会在jQuery中消失。

+1

Thanx!这解决了我的问题。辉煌!终于星期五!;) – 2014-10-03 09:10:18

0

您可以将$ .ajax的async属性设置为false。默认情况下是真的。

$.ajax({  
     type: "POST", 
     async : false, 
     url: serviceRoot + "InsertTextbatchTagItem", 
     beforeSend: serviceFramework.setModuleHeaders, 
     data: item, 
     cache: false 
    }); 
+0

@op我敦促你不要采取这种方法 – andrew 2014-10-03 09:03:41

+0

@andrew,我同意你的看法,那就是回调应该是这种场景的理想人选。 – 2014-10-03 09:05:09