【问题标题】:Need help implementing Deferred on a JSON/AJAX post需要帮助在 JSON/AJAX 帖子上实现 Deferred
【发布时间】:2013-10-31 16:33:48
【问题描述】:

我正在编写一个测验,通过异步 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 = 结果)是“CAUTION BROKEN CODE”,因为“A 代表异步”。 :) http://jqfundamentals.com/chapter/ajax-deferreds

无论如何,请告诉我如何调整上面的代码以使用延迟方法,而不是我目前使用的损坏方法。感谢您的帮助。

【问题讨论】:

标签: jquery ajax json jquery-deferred


【解决方案1】:

$.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()(用于已解决的承诺)和deferred.fail()(用于被拒绝的承诺)。

============================================

以下是我根据@giaour 的建议的完整实现,供任何感兴趣的人参考。谢谢。

点击提交按钮时调用。

     var fetchAnswer = recordAnswer(answer);
     fetchAnswer.then(function (result) {
        // Do something
        recalculateProgress(result.IsComplete, result.IsAnswerCorrect);
     });

这使用延迟与 AJAX 帖子。

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();
};

感谢大家的帮助。

【讨论】:

  • 感谢@giaour 的解决方案。我就是这么跑的。
【解决方案2】:

异步代码应该是这样的,使用回调函数

 var answerResult = recordAnswer(answer, function(answerResult){
     if (answerResult.IsAnswerCorrect) {
        // Show student if her quiz answer was correct.
     }
 );

 var recordAnswer = function (answer , cb) {
  $.ajax({
    .......
     success: function (result) {
        cb(result);
     },
    .......

【讨论】:

    【解决方案3】:

    主要问题是,尽管您将 async 设置为 false,但您无法保证 return answerResult; 将在成功功能后执行。

    所以,我认为更好的方法是在成功触发时触发回调函数并执行它必须执行的操作。您可以将调用对象传递给 recordAnswer 函数并在回调函数中使用它。

    【讨论】:

    • 好的,只需要寻找farmer1992的解决方案。这正是我要说的,但是用代码写的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-12
    • 1970-01-01
    相关资源
    最近更新 更多