我有一个按钮,我想跟踪用户按下它,如果跟踪ajax调用返回数据,然后执行一个承诺,当这一切都完成后,继续按钮事件。
以下是我到目前为止所做的事情,但按钮事件和第二个承诺同时发生。按钮事件不等待第二个承诺解决
$('.my_button').on('click', function() {
ui_tracking('button_1').then(function () {
alert('Hello');
});
});
function ui_tracking(type, payload) {
var deferred = $.Deferred();
var log_action = function () {
$.ajax({
url: '/api/submit_action',
type: 'POST',
dataType: 'json',
data: {
type: type,
payload: JSON.stringify(payload)
},
success: function(results, textStatus, xhr) {
if (typeof(results) !== 'undefined' && results !== null) {
if (typeof(results.data) !== 'undefined' && results.data !== null) {
if (results.data.question) {
startQuestion(results.data.question).then(function () {
deferred.resolve();
}, function() {
deferred.reject();
});
}
}
}
deferred.resolve();
},
error: function (xhr, textStatus, errorThrown) {
deferred.reject();
}
});
};
log_action();
return deferred.promise();
}
function startQuestion(question_data) {
var deferred = $.Deferred();
var openQuestion = function () {
$('#question-modal .modal-body .question').html(question_data.question).attr('data-question-id', question_data.id);
$('#question-modal').modal('show').on('hidden.bs.modal', function (e) {
deferred.resolve();
$('#question-modal').unbind('hidden.bs.modal');
});
};
openQuestion();
return deferred.promise();
}
SF
答案 0 :(得分:0)
您的成功:立即回调deferred.resolve();
(最后,在if条件之后)
success: function(results, textStatus, xhr) {
if (typeof(results) !== 'undefined' && results !== null) {
if (typeof(results.data) !== 'undefined' && results.data !== null) {
if (results.data.question) {
startQuestion(results.data.question).then(function () {
deferred.resolve();
}, function() {
deferred.reject();
});
}
}
}
// this gets called regardless of the above conditions!
deferred.resolve();
知道$ .ajax返回一个(jQuery)Promise,我相信你可以简化ui_tracking函数,如下所示:
function ui_tracking(type, payload) {
return $.ajax({
url: '/api/submit_action',
type: 'POST',
dataType: 'json',
data: {
type: type,
payload: JSON.stringify(payload)
}
}).then(function(results) {
if (results && results.data && results.data.question) {
return startQuestion(results.data.question);
}
});
}
在上面。然后,如果条件不满足,则返回undefined
...基本上与使用deferred.resolve()
时相同 - 返回的Promise将被解析为{ {1}}一旦ajax完成
但是,如果条件都满足,则返回是undefined
返回的Promise - 这意味着返回的Promise将是startQuestion
返回的Promise - 因此您的代码将等待承诺在继续之前解决
此外,不需要简单地返回被拒绝的承诺的错误处理 - 让外部调用处理错误
或者,您可以将整个批次写为
startQuestion
当然逻辑已经发生了变化,所以可能并不完全是你想要的
答案 1 :(得分:0)
您可以封装每个"步骤"在函数中返回一个promise(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)然后" chain"他们。
这是一篇关于在一系列中执行承诺的好文章:http://www.datchley.name/promise-patterns-anti-patterns/#executingpromisesinseries(你可能需要为你的承诺提供一个polyfill:https://github.com/stefanpenner/es6-promise)