我有一个返回函数但是在函数中有一个异步请求,它保存了函数返回的值。我理解异步请求的性质,函数将完成,并且在等待异步函数完成时不返回值。
我尝试使用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
};
答案 0 :(得分:2)
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),其他函数将订阅并知道如何处理所述事件。