fakebackend 拦截器错误消息:"Username "undefined" is already taken"

fakebackend interceptor error message: "Username "undefined" is already taken"

我正在关注此 tutorial 以实现一个简单的 signup/login 功能,其中包含一个假后端拦截器。到目前为止,我刚刚构建了注册组件、用户模型和服务,以及与假 API 匹配的相应端点。但是当我将凭据发送到服务器时,我收到此错误:error: {message: "Username "undefined" is already taken"} 好像根本没有发送任何凭据...

假后端:

    ...The imports...
    
// array in local storage for registered users
    let users = JSON.parse(localStorage.getItem('users')) || [];
    
    @Injectable()
    export class FakeBackendInterceptor implements HttpInterceptor {
        intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            const { url, method, headers, body } = request;
    
            // wrap in delayed observable to simulate server api call
            return of(null)
                .pipe(mergeMap(handleRoute))
                .pipe(materialize()) // call materialize and dematerialize to ensure delay even if an error is thrown (https://github.com/Reactive-Extensions/RxJS/issues/648)
                .pipe(delay(500))
                .pipe(dematerialize());
    
            function handleRoute() {
                switch (true) {
                    case url.endsWith('/users/register') && method === 'POST':
                        return register();
                    case url.endsWith('/users/authenticate') && method === 'POST':
                        return authenticate();
                    case url.endsWith('/users') && method === 'GET':
                        return getUsers();
                    case url.match(/\/users\/\d+$/) && method === 'GET':
                        return getUserById();
                    case url.match(/\/users\/\d+$/) && method === 'DELETE':
                        return deleteUser();
                    default:
                        // pass through any requests not handled above
                        return next.handle(request);
                }
            }
    
            // route functions
    
            function register() {
                const user = body
    
                if (users.find(x => x.username === user.username)) {
                    return error('Username "' + user.username + '" is already taken')
                }
    
                user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
                users.push(user);
                localStorage.setItem('users', JSON.stringify(users));
    
                return ok();
            }
    
            function authenticate() {
                const { username, password } = body;
                const user = users.find(x => x.username === username && x.password === password);
                if (!user) return error('Username or password is incorrect');
                return ok({
                    id: user.id,
                    username: user.username,
                    firstName: user.firstName,
                    lastName: user.lastName,
                    token: 'fake-jwt-token'
                })
            }
    
            function getUsers() {
                if (!isLoggedIn()) return unauthorized();
                return ok(users);
            }
    
            function getUserById() {
                if (!isLoggedIn()) return unauthorized();
    
                const user = users.find(x => x.id == idFromUrl());
                return ok(user);
            }
    
            function deleteUser() {
                if (!isLoggedIn()) return unauthorized();
    
                users = users.filter(x => x.id !== idFromUrl());
                localStorage.setItem('users', JSON.stringify(users));
                return ok();
            }
    
            // helper functions
    
            function ok(body?) {
                return of(new HttpResponse({ status: 200, body }))
            }
    
            function unauthorized() {
                return throwError({ status: 401, error: { message: 'Unauthorised' } });
            }
    
            function error(message) {
                return throwError({ error: { message } });
            }
    
            function isLoggedIn() {
                return headers.get('Authorization') === 'Bearer fake-jwt-token';
            }
    
            function idFromUrl() {
                const urlParts = url.split('/');
                return parseInt(urlParts[urlParts.length - 1]);
            }
        }
    }
    
    export const fakeBackendProvider = {
        // use fake backend in place of Http service for backend-less development
        provide: HTTP_INTERCEPTORS,
        useClass: FakeBackendInterceptor,
        multi: true
    };

注册组件:

ngOnInit() {
    this.registerForm = this.fb.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      userName: ['', Validators.required],
      password: [null,[ Validators.required, Validators.minLength(6)]]
    })
  }

  get firstName() { return this.registerForm.get('firstName') }
  get lastName() { return this.registerForm.get('lastName') }
  get userName() { return this.registerForm.get('userName') }
  get password() { return this.registerForm.get('password') }

  onSubmit() {
    if (this.registerForm.invalid) return;
      this.userService.register(this.registerForm.value).subscribe(
        data => {
           console.log(data)
        },
        error => {
           console.log(error)
        });
     
  }

和服务:

constructor(private http: HttpClient) { }

   register(credentials){
    console.log(credentials)
    return this.http.post(`/users/register`, credentials)
  }

这是控制台的快照

我还没有实现所有功能,例如消息服务,但我的问题是,为什么我会从后端收到此响应?我不应该获得 200 状态,因为注册功能设置为这样做吗?注意:app.module 已正确设置,因为 fakebackend 已注册。此外,如果我尝试使用此设置获取用户,我会得到一个 401,这是正确的,因为我没有登录,因此拦截器正在工作。有人可以帮我吗?

在您的表单中,您正在使用 userName,而在拦截器中,您正在检查 username。如果你要在浏览器中清除你的 localStorage,你可能会注意到它第一次工作!为什么...?

好的,第一次你的数组是空的:

let users = JSON.parse(localStorage.getItem('users')) || [];

因此,如果您键入用户名 test,您的有效负载将类似于...

{ userName: 'test' }

注意大写 N..所以这通过了:

if (users.find(x => x.username === user.username)) {
  return error('Username "' + user.username + '" is already taken');
}

因为数组最初是空的。

然后你这样做:

 user.id = users.length ? Math.max(...users.map(x => x.id)) + 1 : 1;
 users.push(user);
 localStorage.setItem("users", JSON.stringify(users));

所以您现在存储在 users 中的是

[{userName: 'test'}]

现在第二次不及格了!由于 find 现在将 undefinedundefined 进行比较,因为 username 属性 不存在于您在 find 中比较的任何一个对象中。 .. undefined === undefined 是真实的,因此它将 return 您的 users 数组中的第一项。

将您的比较更改为:

if (users.find(x => x.userName === user.userName))

它会正常工作。 Oooooor 将表单控件名称更改为 username...