Angularjs 这是一个;延迟反模式“;?
我发现很难理解“延迟反模式”。我想我从原则上理解它,但我还没有看到一个超级简单的例子来说明什么是服务,有不同的承诺,也有不同的反模式,所以我想我应该试着做我自己的,但鉴于我对它的了解不是超级的,我会先得到一些澄清 我在一家工厂(某某工厂)有以下信息: 我检查其对象的原因只是为了在Angularjs 这是一个;延迟反模式“;?,angularjs,angularjs-directive,angularjs-service,angular-promise,Angularjs,Angularjs Directive,Angularjs Service,Angular Promise,我发现很难理解“延迟反模式”。我想我从原则上理解它,但我还没有看到一个超级简单的例子来说明什么是服务,有不同的承诺,也有不同的反模式,所以我想我应该试着做我自己的,但鉴于我对它的了解不是超级的,我会先得到一些澄清 我在一家工厂(某某工厂)有以下信息: 我检查其对象的原因只是为了在$http.get() 下面,在我的指示中: this.var = SomeFactory.getData() .then(function(response) { //some variable
$http.get()
下面,在我的指示中:
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
})
.catch(function(response) {
//Do error handling here
});
据我所知,这是一个反模式。因为最初的延迟承诺抓住了错误并简单地将其吞下。它不会返回错误,所以当调用这个“getData”方法时,我必须执行另一个捕获来捕获错误
如果这不是反模式,那么有人能解释为什么两者都需要某种“回调”吗?当我第一次开始编写这个工厂/指令时,我预计必须在某个地方执行一个不同的承诺,但我没有预料到必须在两侧执行.catch()
(也就是说,如果我执行SomeFactory.getData()
这是“延迟反模式”吗
是的。当创建一个新的冗余延迟对象以从承诺链内部解析时,会发生“延迟反模式”。在您的情况下,您使用$q为隐式返回承诺的内容返回承诺。您已经有了承诺对象($http服务
本身返回一个承诺
),所以您只需要返回它
下面是一个超级简单的例子,说明了一个服务,一个是延迟承诺,一个是反模式
这是反模式
这是你应该做的
app.factory("SomeFactory",['$http']){
return {
getData: function(){
//$http itself returns a promise
return $http.get(destinationFactory.url);
}
}
而两者的消费方式是相同的
this.var = SomeFactory.getData()
.then(function(response) {
//some variable = response;
},function(response) {
//Do error handling here
});
这两个例子都没有错(至少在语法上是如此)…但第一个是多余的…而且不需要
希望它能有所帮助:)我认为这是经典的延迟反模式,因为您正在创建不必要的延迟对象。但是,您正在通过验证为链添加一些价值。通常,在我看来,当创建延迟对象的好处很少或没有好处时,反模式尤其糟糕 因此,代码可以简单得多
$q
承诺有一个小小的文档化功能,可以将承诺中返回的任何内容自动包装到承诺中(使用$q.when
)。在大多数情况下,这意味着您不必手动创建延迟:
var deferred = $q.defer();
然而,这就是文档演示如何将承诺与$q
一起使用的方式
因此,您可以将代码更改为:
return {
getData: function(){
return $http.get(destinationFactory.url)
.then(function (response) {
if (typeof response.data === 'object') {
return response.data;
} else {
throw new Error('Error message here');
}
});
// no need to catch and just re-throw
});
}
使用是一种延迟的反模式
反模式
vm.download = function() {
var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
return $q(function(resolve, reject) {
var req = {
method: 'POST',
url: url,
responseType: 'arraybuffer'
};
$http(req).then(function(response) {
resolve(response.data);
}, function(error) {
reject(error);
});
});
}
正确的
vm.download = function() {
var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
var req = {
method: 'POST',
url: url,
responseType: 'arraybuffer'
};
return $http(req).then(function(response) {
return response.data;
});
}
$http服务已经返回了一个承诺。使用是不必要的,而且容易出错。好的,因为添加了灯光验证,所以我应该保留“回调”-然后我就离开了,因为我在返回它之前用它做了一些事情?在使用它之前在承诺内做一些工作有多普遍?我更喜欢NLN的答案的外观,但他不得不放弃我的验证…从承诺链读取数据,做一些逻辑,然后返回数据进行进一步处理是非常常见的。这就是我所做的让它成为一条链条:)。最后,您到达末尾并将数据绑定到
$scope
或任何地方。因此,这里的问题真的是不必要地涉及$q
?是的,您可以想象您有一个包含多个层的承诺链。为链中的每个链接创建一个延迟的
,会很麻烦,也没有必要。您好,NLN,谢谢您的回复。那么,在您的示例中,是否要包含typeof
验证,或者在从工厂检索后在控制器中进行验证?嗨,Aleski。您可以在.success()
函数:)中执行typeof
验证。我未登录就进行了编辑,现在已锁定。基本上,.success和.error已被弃用。您可以直接使用。那么现在。@SenHeng:您的编辑看起来不错(而且是必要的,sortof),谢谢:)我不认为第一个是多余的,也不需要。您可能希望在工厂中操作数据,并在那里保存其他控制器共享的值。。。
vm.download = function() {
var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
return $q(function(resolve, reject) {
var req = {
method: 'POST',
url: url,
responseType: 'arraybuffer'
};
$http(req).then(function(response) {
resolve(response.data);
}, function(error) {
reject(error);
});
});
}
vm.download = function() {
var url = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
var req = {
method: 'POST',
url: url,
responseType: 'arraybuffer'
};
return $http(req).then(function(response) {
return response.data;
});
}