Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jquery 返回已解决的承诺_Jquery_Jquery Deferred - Fatal编程技术网

Jquery 返回已解决的承诺

Jquery 返回已解决的承诺,jquery,jquery-deferred,Jquery,Jquery Deferred,我有一个现有的项目,它有很多异步函数,可以返回承诺。我正在添加一些缓存,以便在某些情况下异步函数将同步完成,并希望尽可能缩短/改进此代码: return $.Deferred(function(def) { def.resolve(); }).promise(); 例如,我有一个数据服务类,它处理大多数AJAX请求,如下所示: function DataService() { var self = this; self.makeRequest = funct

我有一个现有的项目,它有很多异步函数,可以返回承诺。我正在添加一些缓存,以便在某些情况下异步函数将同步完成,并希望尽可能缩短/改进此代码:

        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,而是执行一些同步工作,然后返回。不过,它需要返回一个承诺,因为不管它叫什么,它都会期待,但它需要是一个“已经完成/解决的承诺”。目前我正在使用上面的第一组代码来实现这一点。看来一定有更好的办法。

@Eselk

根据我的经验,
$.Deferred(函数(def){…})构造很少需要,尽管我想它在某些情况下非常有用

首先:

return $.Deferred(function(def) { def.resolve(); }).promise();
将简化为:

return $.Deferred().resolve().promise();
其次,在
DataService.makeRequest()
中,您可以通过利用
.then()
来避免显式
$.Deferred
,如下所示:

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(null,…)
    -导致传递一个新的承诺,并使用与
    $.ajax()
    返回的原始承诺相同的值进行解析。因此,在“完成”(即ajax成功)条件下,
    .then()
    是完全透明的
  • 返回exmessage-导致传递新承诺,并以
    ex.message
    拒绝
虽然,IMHO,链接
.then()
比在
$.Deferred()回调中设置所有内容要干净得多,但是nett效果应该与原始代码相同

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

$message = "my custom message";
header("HTTP/1.1 421 $message");
exit(0);
我相信ASP提供了同样的功能


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

只需使用
返回$.when()
返回已解析的承诺

如果根本不传递任何参数,jQuery.when()将返回一个 决心承诺

参考资料:


注意事项:

  • 这与
    return$.when(未定义)相同
    这导致了下面一个相当酷的技巧,它避免了使用数组和
    apply
如果要等待可变数量的承诺并行完成,则可以在循环中使用此模式:

var promise;   // Undefined is treated as an initial resolved promise by $.when
while (insomeloop){
    promise = $.when(promise, newpromise);
}
然后在完成时进行最后一次通话:

promise.then(function(){
    // All done!
});
e、 g

缺点很小:

将以前的承诺包装成新的承诺时,每次调用
。开销很小,您不再需要维护和评估一系列承诺
  • 没有值可以直接传递给最终函数。由于您通常不希望从并行承诺返回值,因此这是次要的
  • 单个承诺的失败将提前中止最终等待,因此您需要确保所有承诺都能实现

  • 感谢您提供的所有信息。我决定我需要我的ajax调用在更高级别上可以取消,所以我现在在大多数地方返回延迟,所以根据您的回答,我只需要$.Deferred.resolve();--漂亮干净。我想你的意思是
    $.Deferred().resolve().promise()将无法解析,但是即使是
    未定义的
    as参数也将解析。奇怪。
    var promise;$.when
    var $elements = $('.some-elements');
    $elements.each(function(){
         var $element = $(this).fadeout();
         promise = $.when(promise, $element.promise());
    });
    promise.then(function(){
        // All promises completed!
    });