这个问题当然可以应用于jQuery,但在这种情况下,我指的是Prototype。在原型文档中,
由于同步使用令人不安,而且通常味道不好应该避免改变这一点。认真地
我不确定使用同步ajax调用有什么缺点。似乎在许多情况下,您必须等待调用返回(而不使用特定的回调函数)。例如,我目前使用Prototype的onSuccess, onFailure and onComplete
来处理其余的代码。
然而,我使用的web服务(都是内部的)涵盖了大多数项目,我的任务是创建更多可重用的代码。一个例子是一个返回客户属性的客户类。一个简单的例子(请记住,我只展示了保持简单的基本功能):
Customer = Class.create({
initialize: function(customerId) {
new Ajax.Request('some-url', {
method: 'get',
parameters: {
customerId: customerId
},
onSuccess: this.setCustomerInfo.bind(this)
}
},
setCustomerInfo: function(response) {
//for the sake of this example I will leave out the JSON validation
this.customerInfo = response.responseText.evalJSON();
}
});
因此,使用这个简单的类,我可以在任何项目中执行以下操作来获取客户信息。
var customer = new Customer(1);
//now I have the customer info
document.write(customer.customerInfo.firstName);
使用上述代码不会打印出客户的名字。这是由于ajax调用是异步的。无论web服务是否带回客户数据,它都将执行document.write
。但在数据返回并设置客户变量之前,我不想做任何事情。为了解决这个问题,我将ajax调用设置为同步,这样浏览器在new Customer(1);
完成之前不会继续打开。
这个方法似乎有效(将异步设置为false),但阅读Prototype文档让我停顿了一下。使用这种方法的缺点是什么?有没有其他方法可以做到这一点,更高效等等?
如果有任何反馈,我将不胜感激。
让我们提醒您,JavaScript是单线程
同步IO调用阻塞整个线程
一个简单的修复方法是使用异步风格的回调编程。
Customer = Class.create({
initialize: function(customerId, cb) {
new Ajax.Request('some-url', {
method: 'get',
parameters: {
customerId: customerId
},
onSuccess: (function() {
this.setCustomerInfo.apply(this, arguments);
cb.apply(this, arguments);
}).bind(this)
}
},
setCustomerInfo: function(response) {
//for the sake of this example I will leave out the JSON validation
this.customerInfo = response.responseText.evalJSON();
}
});
var c = new Customer(1, function() {
document.write(customer.customerInfo.firstName);
});
好吧,除了非常而不是JavaScript之外,它还有一些令人愉快的效果,比如完全屏蔽浏览器的UI。这不是一个小问题。
做了一些研究,发现了一些很酷的东西。原型基于XMLHttpRequest.open的"异步"。根据维基百科的说法,这不是规范中不需要的部分,它将阻止"onreadystatechange"。
大多数人不赞成同步ajax调用,因为它会冻结UI直到完成,因为它不允许代码继续执行直到完成。我想你可以说,这会导致界面的结结巴巴。
好吧,如果用户在同步调用完成时生成加载图像,那么我不认为阻塞UI是个问题。这可能与提交表格相同。