jquery - 返回已解决的 promise

标签 jquery jquery-deferred

我有一个现有的项目,其中有很多返回 Promise 的异步函数。我添加了一些缓存,以便在某些情况下异步函数将同步完成,并希望尽可能使此代码更短/更好:

        return $.Deferred(function(def) { def.resolve(); }).promise();

例如,我有一个处理大多数 AJAX 请求的数据服务类,如下所示:

function DataService() {

    var self = this;

    self.makeRequest = function(functionName, data) {
        return $.Deferred(function(def) {

            var jsonData = JSON.stringify(data);

            $.ajax({
                type: "POST",
                url: "WebService.asmx/" + functionName,
                data: jsonData,
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                error: function(xhr, status, error) {
                    var ex;
                    try {
                        ex = eval("(" + xhr.responseText + ")");
                        ex.message = ex.Message;
                        ex.Message = undefined;
                    } catch (ex2) {
                        ex = { message: "Invalid Response From Server:\r\n" + xhr.responseText };
                    }
                    if (ex.message == "LoginRequired") {
                        app.viewModels.main.loginRequired(true);
                    }
                    else {
                        app.showError(ex.message);
                    }
                    def.reject(ex.message);
                }
            });
        }).promise();
    }
}

然后我在另一个类中有一个函数,当前总是调用 makeRequest:

self.deleteMe = function()
{
   return app.dataservice.makeRequest('deleteItem');
}

我想更新deleteMe函数,这样它就不会总是调用makeRequest,而只是做一些同步工作然后返回。但它需要返回一个 promise ,因为无论调用什么,它都会期待这一点,但它需要是一个“已经完成/解决的 promise ”。目前我正在使用上面的第一组代码来做到这一点。看来一定有更好的方法。

最佳答案

@Eselk,

根据我的经验,$.Deferred(function(def) {...});很少需要构建,尽管我认为它在某些情况下可能非常有用。

首先:

return $.Deferred(function(def) { def.resolve(); }).promise();

将简化为:

return $.Deferred().resolve().promise();

其次,在 DataService.makeRequest()您可以避免显式 $.Deferred 的需要通过利用.then() ,如下:

function DataService() {
    var self = this;
    self.makeRequest = function (functionName, data) {
        return $.ajax({
            type: "POST",
            url: "WebService.asmx/" + functionName,
            data: JSON.stringify(data),
            contentType: "application/json; charset=utf-8",
            dataType: "json"
        }).then(null, function (xhr, status, error) {
            var ex;
            try {
                ex = eval("(" + xhr.responseText + ")");
                ex.message = ex.Message;
                ex.Message = undefined;
            } catch (ex2) {
                ex = {
                    message: "Invalid Response From Server:\r\n" + xhr.responseText
                };
            }
            if (ex.message == "LoginRequired") {
                app.viewModels.main.loginRequired(true);
            } else {
                app.showError(ex.message);
            }

            return ex.message;
        });
    };
}

这里的关键方面是:

  • $.ajax()返回一个与 Promise 兼容的 jqXHR 对象,该对象(成功/错误时)立即由 .then() 执行和修改。 .
  • .then(null, ...) - 导致传递一个新的 Promise,并使用与 $.ajax() 返回的原始 Promise 相同的值进行解析。 。因此,在“完成”(即ajax成功)条件下,.then()完全透明。
  • return ex.message; - 导致新的 promise 被传递,被 ex.message 拒绝.

净效果应该与您的原始代码相同,恕我直言,链接 .then()比在 $.Deferred() 中设置所有内容要干净得多回调。

顺便说一句,您也许可以避免使用 eval("(" + xhr.responseText + ")")等,通过在服务器端设置适当的 HTTP header ,使您的“.Message”直接显示为 status失败回调的参数(或xhr.status?)。例如,在 PHP 中,您可以执行以下操作:

$message = "my custom message";
header("HTTP/1.1 421 $message");
exit(0);

我确信 ASP 提供相同的功能。

IIRC,任何 4xx 系列状态代码都可以完成这项工作。 421恰好是一个没有特定含义的数字。

关于jquery - 返回已解决的 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16659630/

相关文章:

javascript - 收到 AJAX 内容时 $.each 的下一次迭代

php - jquery自动过期div

javascript - 球面全景?

javascript - 队列函数调用

jquery - 重试 jquery ajax 请求,该请求已附加到其延迟的回调

jquery-deferred - jQuery - 延迟等待一组 ajax 请求以完成甚至失败

php - 使用来自 ajax 的数据填充多个下拉列表

javascript - 将 URL 参数传递给 iframe

javascript - javascript/jquery 文件是否有多重包含保护?

jquery - 为什么 $.when() 中没有错误时会触发 failed() ?