jquery-deferred - 返回已经解决的承诺

  显示原文与译文双语对照的内容
0 0

我现有的工程有很多异步函数,这些函数返回的承诺。 我添加一些缓存,以便在某些情况下异步函数都将同步完成并尽量想让这个代码shorter/better :

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

例如,我有一个Data Service类,可处理大多数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:rn" + 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染上了因为不管称它将期待,但它应是一个" 已经completed/resolved承诺" 。 当前我使用上面第一组代码这么做 好像必须有一个更好的方法。

时间:原作者:1个回答

0 0

@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:rn" + xhr.responseText
                };
            }
            if (ex.message == "LoginRequired") {
                app.viewModels.main.loginRequired(true);
            } else {
                app.showError(ex.message);
            }
            return ex.message;
        });
    };
}

这里的关键方面包括:

  • $.ajax()返回一个promise兼容jqXHR对象,该对象( 在success/error ) 会立即采取行动和修改者 .then().
  • .then(null, ...)使新的承诺时要传递,与返回的值相同原始承诺解决 $.ajax(). 於是乎'完成'( 即ajax成功) 条件, .then()是完全透明的。
  • return ex.message;使新的承诺时要传递的,被拒绝, ex.message.

nett效果应该与原始代码虽然相同,imho,链接 .then()明显比设置所有内容在一个干净 $.Deferred()回调。

顺便说一下,你也许能够避免这一 eval("(" + xhr.responseText + ")")etc通过设置适当的HTTP Header服务器端以便你'.Message'直接出现与 status参数( 或 xhr.status- 1 ) 的失败回调。 例如,在PHP可以执行类似操作:

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

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

iirC,任何状态码4xx系列把波斯。 421刚好是一个没有特定含义。

原作者:
...