【发布时间】:2016-06-23 15:00:36
【问题描述】:
假设我们有一个对 API 进行 http 调用以创建用户的服务。根据结果(200 或错误),应用程序应重定向或显示错误(客户端进行了一些验证,但这不是主题,因为验证也应始终发生在服务器端)。
Angular 2 文档指出,让服务返回一个可观察对象并在组件中订阅它是不好的做法。该服务应该是自包含的,并且组件不需要对此有任何了解。拨打userService.createUser(user_data);应该就够了
但是路由应该再次发生在组件中。所以我想知道如何处理这种情况?我的服务应该返回一个新的 Observable 吗?还是只是一个值?但是那我该如何处理异步任务呢?
这样做的正确方法是什么?
我们以这个服务创建用户和这个组件为例:
// user.service.ts:
import { Http, Headers } from '@angular/http';
import { Inject, Injectable } from '@angular/core';
import { API_CONFIG, Config } from '../config/api.config';
import { User } from '../models/user.model';
@Injectable()
export class UserService {
validation_errors: Array<any> = [];
constructor(
@Inject(API_CONFIG) private api_config: Config,
private http: Http,
@Inject(User) public user: User
) {}
createUser(user: User) {
var body = JSON.stringify({ user });
var myHeader = new Headers();
myHeader.append('Content-Type', 'application/json');
this.http.post(this.api_config.apiEndpoint + '/users/', body, { headers: myHeader })
.map(res => res.json())
.subscribe(
res => {
// User was created successfully
this.user = this.fromJson(res.data);
},
err => {
// Something went wrong, let's collect all errors in a class attribute
let errors = err.json().errors;
for(var i = 0; i < errors.length; i++) {
this.validation_errors.push(errors[i])
}
}
);
}
/**
* @param input_json JSON returned from API, formatted according to jsonapi.org, containing one single user.
* @return UserModel instantiated with the values from input_json
*/
fromJson(input_json: any) {
var user:User = new User();
user = input_json.attributes;
user.id = input_json.id;
return user;
}
}
// user.component.ts:
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, REACTIVE_FORM_DIRECTIVES, Validators } from '@angular/forms';
import { Router, RouteParams, ROUTER_DIRECTIVES } from '@angular/router-deprecated';
import { UserService } from '../../shared/index';
@Component({
selector: 'fac-user-editor',
templateUrl: 'app/+users/editor/user-editor.component.html',
styleUrls: ['app/+users/editor/user-editor.component.css'],
directives: [REACTIVE_FORM_DIRECTIVES, ROUTER_DIRECTIVES],
providers: [UserService]
})
export class UserEditorComponent implements OnInit {
// Setup Form
private email_regex = '[a-z0-9\\.\\-\\_]+@[a-z0-9\\.\\-\\_]+\\.[a-z0-9\\.\\-\\_]+';
userForm: FormGroup;
action: string;
idCtrl = new FormControl('');
nameCtrl = new FormControl('', [Validators.required]);
emailCtrl = new FormControl('', [Validators.required, Validators.pattern(this.email_regex)]);
usernameCtrl = new FormControl('', [Validators.required, Validators.minLength(5)]);
passwordCtrl = new FormControl('', [Validators.minLength(8)]);
passwordConfirmationCtrl = new FormControl('');
public user_id: string;
constructor(private userService: UserService, private router: Router, private params: RouteParams) {}
/**
* Handle submit of form
*/
onSubmit(form: any) {
// Here should happen some error handling / routing, depending on the result of the call to the API
this.userService.createUser(this.userService.user);
}
ngOnInit(): any {
this.userForm = new FormGroup({
id: this.idCtrl,
name: this.nameCtrl,
email: this.emailCtrl,
username: this.usernameCtrl,
password: this.passwordCtrl,
password_confirmation: this.passwordConfirmationCtrl
});
}
}
我可以像这样在模板中显示错误消息:
<div class="form-group"
[hidden]="adminService.validation_errors.length === 0"
class="alert alert-warning" role="alert">
<strong>Some errors occured</strong>
<ul>
<li *ngFor="let validation_error of adminService.validation_errors">
<span class="text-capitalize">{{validation_error.source.field}}:</span> {{validation_error.detail}}
</li>
</ul>
</div>
【问题讨论】:
-
您的示例可以工作,但如果其他人(可能是其他服务?)使用
adminService并产生错误怎么办?您的组件会在右侧显示该错误吗? -
@Springrbua:我的例子是一个不好的例子,不应该这样做(即使它有效)。我想使用 Observables 重构它,同时遵循 google 的最佳实践指南。
-
您可以将一个空数组
validation_errors传递给该方法并用错误填充它,以便每次调用都返回它自己的结果。你也可以使用回调函数,但我记得 Angular2 使用Observables等,因为它们比 x 级回调更容易阅读……我自己使用Observables 并订阅它们。我看不出有什么理由不应该在组件中使用它们。我的意思是 Angular2 有一个asyncPipe是为Observables 和Promises 制作的 -
我真的不明白管道如何帮助我处理异步错误。你能举一个返回 Observable 的例子吗?
-
我只是想说,angular2 提供了一个为可观察对象(异步管道)制作的管道。所以我不明白为什么你不应该在你的组件中使用 observables。
标签: javascript angular