如何在 500 毫秒待处理 AJAX 请求后添加微调器?

How to add spinner after 500ms pending AJAX request?

我有一个小问题,我很想用 jQuery 3 正确解决。所以我的想法是这样的:

  1. 执行AJAX请求
  2. 等待回复。如果 500ms 后没有响应,显示 spinner
  3. 收到回复后隐藏微调器。

我目前有一些工作。但问题是:这是正确的还是首选的方式?

// helper function for setTimeout
function wait(ms) {
    var deferred = $.Deferred();
    setTimeout(function() { deferred.resolve() }, ms);
    return deferred.promise();
}

var request = $.ajax({
    dataType: "json",
    url: "/api/articles/?" + $.param(params)
});

wait(500).then(function() {
    if (request.state() === "pending") // works, but the docs says we should do this only for debugging purposes
        $(".spinner").show();
});

request.always(function() {
    $(".spinner").hide();
);

我们可以这样使用request.state()吗?可以用更优雅的方式解决这个问题吗?

你真的应该尝试在不同步检查承诺状态的情况下做这样的事情。

需要对代码进行相当小的修改。

  • return Deferred 来自 wait() 而不是承诺。
  • 调用 wait(500) 并保留对 returned Deferred 的引用。
  • wait(500) 延迟完成时无条件显示微调器。
  • 拒绝 wait(500) 延迟结算 ajax 承诺,从而确保超时无法稍后解决。

这将有效地在 wait(500) 延迟和 $.ajax() 承诺之间建立竞争,前者试图显示微调器而后者试图阻止它。

function delay(ms) {
    return jQuery.Deferred(function(dfrd) {
        setTimeout(dfrd.resolve, ms);
    });
}

var showSpinner = delay(500); // a Deferred that will be resolved after 500ms, unless rejected before that.

showSpinner.then(function() {
    $(".spinner").show();
}, function() {
    console.log('The ajax request settled before the timeout');
});

jQuery.ajax({
    dataType: 'json',
    url: '/api/articles/?' + $.param(params)
}).always(function() {
    $(".spinner").hide(); // hide spinner (if the timeout won the race)
    showSpinner.reject(); // prevent the spinner from being shown
});