jquery - 需要帮助在 JSON/AJAX 帖子上实现 Deferred

标签 jquery ajax json jquery-deferred

我正在编写一个测验,通过异步 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/

相关文章:

javascript - 根据选择的选项运行 JQuery 动画

javascript - 如何查看关联的点击功能码

javascript - 如何在 jquery 中为 ajax post 数据字符串设置隐藏字段的值?

javascript - bLazy 和 Vue.js - DOM 准备得不够快

javascript - 不使用 CSS3 的情况下围绕左下边缘枢轴旋转图像

jquery - 自定义 JQuery 插件

javascript - JS 事件监听器的成本是否比额外的 HTTP 请求还要高?

javascript - javascript/ajax 中的 Google Analytics 目标跟踪

java - [PlayFramework 2.5][Java] JSON post 请求绑定(bind)到表单中

c# - 如何将 javascript 中的 JSON 数组传递到我的代码隐藏文件