我有这个问题:
用户点击按钮A,然后通过ajax调用创建一些东西。该调用返回一些数据。
稍后,用户(将某些文本输入到输入中)将单击按钮B.这将启动另一个ajax调用。现在,这个需要第一个请求返回的数据。
第一次通话足够快时,这没问题。但是,我必须假设它可能需要一段时间,因此当用户点击按钮B时,第一个呼叫可能无法完成。
只要第一次持续,我就不想禁用按钮B.即使第一个ajax调用尚未完成,用户也应该单击按钮B.所以我似乎需要以某种方式对调用进行链接/排队。
我怎么能这样做?如何通过更长的调用序列完成此操作。这个场景是否有一个名称,是否已经存在一种模式?或者我只是失明?
基本示例代码:
$('button.a').click(function () {
$.post('some/url/for/action/a', {})
.done(function (returnedData) {
})
});
$('button.b').click(function () {
// now I need something from returnedData, which may not be available yet
$.post('some/url/for/action/b', {something: returnedData.something})
.done(function () {
})
});
注意:最终目标是加快改善用户体验的过程。
(随意改进问题的标题。我不能更好地表达。)
答案 0 :(得分:3)
如果您可以使用最新版本的ECMAScript规范,那么您可能需要查看使用Promises。有一个非常好的explanation of Promises on Google's documentation for the web,但它们基本上是我们可以用来等待异步完成事情的对象。
如果你在Promise对象中包装你的第一个ajax调用,那么你可以稍后再回来(在你的情况下,在用户点击按钮B之后)并查看它是否已经完成。如果有,then()
你可以做出回应!
var promiseA; // this variable will hold our Promise object
function postActionA() {
return new Promise(function(resolve, reject) {
$.post('some/url/for/action/a', {}).done(resolve); // this is the magic
// when the ajax call completes, it calls the 'resolve' function
});
}
$('button.a').click(function () {
promiseA = postActionA();
// by assigning our promise object to a variable
// we can inspect its state later on
promiseA.then(function(returnedData) {
// do stuff with returnedData here if you like
});
});
$('button.b').click(function () {
// assuming that promiseA was assigned earlier
// we can wait for it to resolve, then make our next ajax call
promiseA.then(function (returnedData) {
$.post('some/url/for/action/b', {something: returnedData.something})
.done(function () {
// do something after the second ajax call completes
});
});
});
如果您无法使用最新版本的ECMAScript而宁愿使用jQuery,我们可以利用jQuery的延迟对象来做类似的事情。
var deferredA; // this variable will hold our Deferred object
$('button.a').click(function () {
deferredA = $.post('some/url/for/action/a', {});
// by assigning our deferred object to a variable
// we can inspect its state later on
deferredA.done(function(returnedData) {
// do stuff with returnedData here if you like
});
});
$('button.b').click(function () {
// assuming that deferredA was assigned earlier
// we can wait for it to resolve, then make our next ajax call
deferredA.done(function (returnedData) {
$.post('some/url/for/action/b', {something: returnedData.something})
.done(function () {
// do something after the second ajax call completes
});
});
});
答案 1 :(得分:1)
我的想法是基于按钮点击排队ajax调用。然后从队列中取出呼叫并解雇。
通过这种方式,您可以单击随机序列(如A,B,A,A,B,A,B,B),并且每个后续调用都将等待之前的序列。
通过全局变量将数据从一个调用传递到另一个调用。
代码:
var queue = [];
var processing = false;
var dataFromLastCall = {}; //data from previous call
function register(callParams){
queue.push(callParams);
if(processing == false){
process(queue);
}
}
function process(){
processing = true;
var call = queue.shift();
$.when(jQuery.ajax(call)).then(function(){
if(queue.length > 0){
process(); //get another
}else{
processing = false; //all done
}
});
}
$("button.a").click(function(e){
e.preventDefault();
register({
type: 'POST',
url: 'some/url/for/action/a',
data: dataFromLastCall,
success: function(newData){
dataFromLastCall = newData;
}
});
});
$("button.b").click(function(e){
e.preventDefault();
register({
type: 'POST',
url: 'some/url/for/action/b',
data: dataFromLastCall,
success: function(newData){
dataFromLastCall = newData;
}
});
});
请注意,此示例不处理错误情况。
答案 2 :(得分:0)
var isFirstCallFinished = false;
$('button.a').click(function () {
$.post('some/url/for/action/a', {})
.done(function (returnedData) {
isFirstCalFinished = true;
})
});
$('button.b').click(function () {
// now I need something from returnedData, which may not be available yet
setInterval(function () {
if(isFirstCallFinished) {
// Cancel Interval
// Call postMe()
}
}, 1000);
});
function postMe() {
$.post('some/url/for/action/b', {something: returnedData.something})
.done(function () {
})
});
}
答案 3 :(得分:-2)
您实际上想要进行同步调用。我建议您使用$.ajax
代替$.post
,因为它可以更加自定义。
您的按钮B功能将是这样的:
$.ajax({
type: 'POST',
url: 'some/url/for/action/b',
data: data,
success: success,
async:false
});
async:false
选项可使您的请求同步。