我正在编写一个测验,通过异步 AJAX/JSON 帖子将答案发送到数据库。数据库返回一个指示符来判断答案是否正确。
一位同事建议使用 $.Deferred,因为无法知道数据库调用返回需要多长时间。我一直无法找到使用 AJAX 帖子执行此操作的明确示例。我认为 StackOverflow 的一位专家可以提供这方面的指导。
此代码位于调用函数中,单击“提交答案”按钮时将执行该函数。
var answerResult = recordAnswer(answer);
if (answerResult.IsAnswerCorrect) {
// Show student if her quiz answer was correct.
}
这是 recordAnswer 函数。这需要在对象中返回几个值(IsAnswerCorrect 和 IsQuizCompleted)。我的表单已成功进行 AJAX 调用,并且值正在返回到“结果”。但有时,返回的“answerResult”值在上面的调用代码中返回为“未定义”,从而导致中断。我相信将其更改为延迟调用将避免该问题。
var recordAnswer = function (answer) {
var quizSessionQuestionId = $('#hidden_quizSessionQuestionId').val();
var numberOfHintsUsed = 0;
var answerResult;
$.ajax({
url: QuizConfig.RecordAnswerDataAction, // Tied to RecordAnswer in BaseQuizController.
type: 'POST',
async: false,
dataType: 'json',
data: {
"quizSessionQuestionId": quizSessionQuestionId,
"value": answer,
"numberOfHintsUsed": numberOfHintsUsed,
"markCompleteIfWrong": false
},
success: function (result) {
answerResult = result;
},
error: function (request, errorm) {
jAlert("Unable to record answer.", "An error occurred while saving this answer.");
return;
}
});
return answerResult;
};
在研究这个问题时,我发现以下教程表明我在上面应用的模式(分配answerResult =结果)是“小心损坏的代码”,因为“A代表异步”。 :) http://jqfundamentals.com/chapter/ajax-deferreds
无论如何,请告诉我如何调整上面的代码以使用延迟方法,而不是我迄今为止使用的损坏方法。感谢您的帮助。
最佳答案
$.Deferred()
对象最好被视为 promise 的经纪人。使用 Promise 进行异步编程的常见模式是使用返回 Promise 而不是值的函数。例如,您可以按如下方式重写您发布的代码:
var recordAnswer = function (answer) {
...
var answerResult = $.Deferred();
$.ajax({
...
success: function (result) {
answerResult.resolve(result);
},
error: function (request, errorm) {
jAlert("Unable to record answer.", "An error occurred while saving this answer.");
answerResult.reject();
}
});
return answerResult.promise();
};
使用 recordAnswer
的代码可以监听解析的 promise ,而不是尝试立即使用返回的值:
var fetchingAnswer = recordAnswer(answer);
fetchingAnswer.then(function(result) {
// do stuff with the result
}
deferred.then()
将在拒绝或解决后执行,因此您可能需要使用 deferred.done()
(对于已解决的 promise )和deferred.fail()
(对于被拒绝的 promise )。
============================================
下面是我根据 @giaour 的建议进行的完整实现,供感兴趣的人引用。谢谢。
单击提交按钮时调用此函数。
var fetchAnswer = recordAnswer(answer);
fetchAnswer.then(function (result) {
// Do something
recalculateProgress(result.IsComplete, result.IsAnswerCorrect);
});
这使用 AJAX post 延迟。
var recordAnswer = function (answer) {
var quizSessionQuestionId = $('#hidden_quizSessionQuestionId').val();
var numberOfHintsUsed = 0;
var promiseBroker = $.Deferred();
$.ajax({
url: QuizConfig.RecordAnswerDataAction,
type: 'POST',
async: false,
dataType: 'json',
data: {
"quizSessionQuestionId": quizSessionQuestionId,
"value": answer,
"numberOfHintsUsed": numberOfHintsUsed,
"markCompleteIfWrong": false
},
success: function (result) {
promiseBroker.resolve(result);
},
error: function (request, errorm) {
jAlert("Unable to record answer.", "An error occurred while saving this answer.");
promiseBroker.reject();
return;
}
});
return promiseBroker.promise();
};
感谢大家的帮助。
关于jquery - 需要帮助在 JSON/AJAX 帖子上实现 Deferred,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19711979/