Dojo使用延迟函数来获取ajax回调函数中的数据

时间:2014-04-23 19:10:42

标签: javascript dojo jquery-deferred deferred

我有一个返回函数但是在函数中有一个异步请求,它保存了函数返回的值。我理解异步请求的性质,函数将完成,并且在等待异步函数完成时不返回值。

我尝试使用dojo延迟函数让我的函数PostInformation()在ajax请求回调中返回一个值。我有一些问题,我不确定我的问题在哪里。以下是我的代码:

Dojo延期功能

function PostInformation(){

      var hasErrors = false;
        var containers = [dijit.byId("container1"), dijit.byId("container2")];
        var Employee = {
            //data
        };

    var def = new dojo.Deferred();

    def = dojo.xhrPost({
        url: 'hello',
        content: Employee,
        load: function (data) {

            formErrors = {
                "errors": true,
                "fName": "123",
                "surname": "456",
                "oNames": "789",
                "bSurname": "784585"
            };

            //formErrors = (JSON.parse(data)).formErrors;

            $.each(formErrors, function (key, value) {

                if (key == 'errors') {
                    hasErrors = value;
                    //console.log('hasErrors set to '+value);
                }
            });

            if (hasErrors == true) {
                for (var i = 0; i < containers.length; i++) {

                    var processingContainer = containers[i];

                    dojo.forEach(processingContainer.getChildren(), function (wid) {
                        var widgetName = wid.attr('id');

                        $.each(formErrors, function (key, value) {

                            if (key == widgetName && value.length > 0) {

                                var myWidget = dijit.byId(widgetName);
                                //var wdgName = dijit.byId(widgetName).attr("id");
                                var myWidgetValue = value;


                                myWidget.validator = function () {
                                    //console.log('Attribute Name is :' + wdgName + ' Error Value is : ' + myWidgetValue);
                                    //console.log(wdgName + " : "+myWidgetValue);
                                    this.set("invalidMessage", myWidgetValue);
                                };
                                myWidget._hasBeenBlurred = true;
                                myWidget.validate();
                            }
                        });
                    });
                }
            } 
            console.log(hasErrors);
            def.resolve(hasErrors);

        },
        error: function(err){
            console.log(err);
            def.reject(err);
        }

    });

    def.then(function(data){

         console.log('In the then function');       
        //alert('In the def.then and the results is : ' + data);
         if(data == true){           
             return false;
         }else{return true;}

    },function(err){
        return false;
        alert('In the def.error and there has been an error ' + err);
    }); 

    //return the value of hasErrors here
};

3 个答案:

答案 0 :(得分:2)

Devdar,你正在做一些非常简单的事情。特别是,您不需要遍历对象来访问其中一个属性,并且变量hasErrors不是必需的。

您的代码应简化为以下内容:

function PostInformation() {
    var $containers = $("#container1, #container2");
    var Employee = {
        //data
    };
    return dojo.xhrPost({
        url: 'hello',
        content: Employee
    }).then(function(data) {
        data = JSON.parse(data);
        var formErrors = data.formErrors;
        if(formErrors.errors) {
            $containers.each(function(i, c) {
                $(c).children().each(function(wid) {
                    var val = formErrors[wid.id],
                        myWidget;
                    if(val) {
                        myWidget = dijit.byId(wid.id);
                        myWidget.validator = function() {
                            this.set("invalidMessage", val);
                        };
                        myWidget._hasBeenBlurred = true;
                        myWidget.validate();
                    }
                });
            });
            //Send an enhanced error object down the "error" route 
            throw $.extend(formErrors, {
                'message': 'PostInformation(): validation failure'
            });
        }
        //Send the data object down the "success" route 
        return data;
    });
};

PostInformation().then(function(data) {
    console.log('PostInformation(): everything went OK');
    //access/process `data` here if necessary
    //and/or just display a nice "success" message to the user
}, function(err) {
    console.error(err.message);
});

除了我自己的错误,这段代码应该做你想要的一切,甚至更多。与您自己的代码一样,它处理服务器的JSON响应并返回Promise,但相似性停止的地方。

在你的代码中,你试图返回一个Promise,它最终用一个布尔值来解析,以指示是否检测到错误。虽然这将(如果正确编写)满足您的直接需求,但它不是最好的Promise逻辑。

在我的代码中,只有在验证成功且拒绝的情况下,如果验证因任何原因失败,则Promise 已解决。这不仅是Promise的逻辑正确行为(成功沿着成功路线走下去,错误沿着错误路线走下去),但作为奖励应该(参见下面的注释)也允许您将更多信息传递给最终的函数处理错误。我选择通过错误消息传递整个formErrors对象,从而在错误处理程序中提供了很大的自由度,可以根据需要尽可能多地显示/ log / etc,并且几乎没有内部假设PostInformation()关于随后会发生什么。您目前认为您只会阅读布尔值formErrors.errors并对其采取行动,但尽可能多地传递错误数据可能会有所帮助,从而让您可以自由地在以后更改您的思想而无需更改任何内容PostInformation()

在这方面,您可以将PostInformation()视为服务器端服务的代理;并且就像那项服务一样,它可以用不完整的知识(或者根本就没有知识)来编写它所传递的(承诺)数据/错误将如何被消费者代码&#34;使用。


注意:我必须承认我并不是100%熟悉Dojo的Promise,所以我不确定JS plain对象是否可以按照我指示的方式抛出。我找到了证据,但没有证据证明它可以。出于这个原因,我谨慎地说,#34;你的代码应该简化为类似的东西&#34;无论如何,除了这个问题之外,在成功路线上发送成功的原则和错误路线上的错误仍应适用。

答案 1 :(得分:1)

我建议您创建自己的Deferred()对象,从PostInformation()函数返回,然后在其上注册.then()处理程序,以便您可以选择解决方案或拒绝在你自己的PostInformation()函数内发生的延迟对象。

你拥有它的方式是你创建了自己的Deferred()对象,但是然后立即用xhrPost返回结果覆盖它,这意味着def现在是其他东西而你没有返回你的延迟PostInformation()因此可以在该功能之外使用它来跟踪进度。

function PostInformation() {
    var hasErrors = false;
    var containers = [dijit.byId("container1"), dijit.byId("container2")];
    var Employee = {
        //data
    };
    var def = new dojo.Deferred();
    dojo.xhrPost({
        url: 'hello',
        content: Employee,
        load: function (data) {
            formErrors = {
                "errors": true,
                "fName": "123",
                "surname": "456",
                "oNames": "789",
                "bSurname": "784585"
            };
            //formErrors = (JSON.parse(data)).formErrors;
            $.each(formErrors, function (key, value) {
                if (key == 'errors') {
                    hasErrors = value;
                    //console.log('hasErrors set to '+value);
                }
            });
            if (hasErrors == true) {
                for (var i = 0; i < containers.length; i++) {
                    var processingContainer = containers[i];
                    dojo.forEach(processingContainer.getChildren(), function (wid) {
                        var widgetName = wid.attr('id');
                        $.each(formErrors, function (key, value) {
                            if (key == widgetName && value.length > 0) {
                                var myWidget = dijit.byId(widgetName);
                                //var wdgName = dijit.byId(widgetName).attr("id");
                                var myWidgetValue = value;
                                myWidget.validator = function () {
                                    //console.log('Attribute Name is :' + wdgName + ' Error Value is : ' + myWidgetValue);
                                    //console.log(wdgName + " : "+myWidgetValue);
                                    this.set("invalidMessage", myWidgetValue);
                                };
                                myWidget._hasBeenBlurred = true;
                                myWidget.validate();
                            }
                        });
                    });
                }
            }
            console.log(hasErrors);
            def.resolve(hasErrors);
        },
        error: function (err) {
            console.log(err);
            def.reject(err);
        }
    });
    return def.promise;
};

PostInformation().then(function (data) {
     console.log('In the then function');
     // process data value here which will contain the value you resolved with
  }, function(err)
      // process an error in the ajax result here
});

答案 2 :(得分:0)

我认为这更像是设计功能的问题。

由于xHR调用是异步的,因此postInformation不应该真正返回任何内容,除非它是Deferred对象本身。另一种选择是让postInformation执行某种事件发布(dojo / topic),其他函数将订阅并知道如何处理所述事件。