我正在使用Aurelia框架构建一个相当高级的应用程序,该框架使用模型,服务和自定义元素。
我有一个包含用户名,电子邮件等的用户模型以及一个bool isLoggedIn。
我有一个用户服务,它将用户存储在localStorage中,允许您更新用户数据等。
我终于有了一些自定义元素,它们使用用户服务来获取当前用户并显示取决于用户是否登录的UI。
我面临的问题是,在我使用用户服务提取用户之后,然后从我的一个自定义元素(存储在用户服务中)更新用户模型另一个自定义元素&# 39;对所述用户模型的引用不会更新。
我试图在JSFiddle中复制这个问题(简单的JS - 我在ES6中写这个)但是没有这样做,在小提琴中一切正常。
有相当多的代码,但我想听听你的意见,我可能做错了这件事发生了什么?
以下是我所拥有的要点:
user.model.js
export class User {
username = '';
isLoggedIn = false;
constructor (data) {
Object.assign(this, data);
}
}
user.service.js
import { User } from 'user.model';
export class UserService {
constructor () {
this.user = null;
}
getUser () {
// User is cached
if (this.user) {
return Promise.resolve(this.user);
}
// Check if we have localStorage
var user = window.localStorage.getItem('user');
if (user) {
this.user = new User(JSON.parse(user));
return Promise.resolve(this.user);
}
// No user - create new
this.user = new User();
return Promise.resolve(this.user);
}
saveUser () {
this.getUser().then(() => {
window.localStorage.setItem('user', JSON.stringify(this.user));
});
}
updateUser (user) {
this.getUser().then(() => {
Object.assign(this.user, user);
this.saveUser();
});
}
login () {
this.updateUser({
isLoggedIn: true
});
return Promise.resolve(true);
}
}
自定义-element.js
import { inject } from 'aurelia-framework';
import { UserService } from 'user.service';
@inject (UserService)
export class CustomElement {
constructor (userService) {
this.userService = userService;
}
attached () {
this.userService.getUser().then(user => {
this.user = user;
console.log('Fetched user:');
console.dir(this.user);
console.log('Same?');
console.dir(this.user === user); // this is true
});
// At some point another custom element fires the UserService.login() method
// Here we check that our reference to the user also updates
setInterval(() => {
console.log('Is user logged in?');
console.dir(this.user.isLoggedIn); // This is always false - even after UserService.login() has been called and UserService.user is updated (if I console.dir this.user inside UserService it is indeed updated)
// Grab a new version of UserService.user
this.userService.getUser().then(user => {
console.log('Fetched new user, is new user and our user same?');
console.dir(this.user === user); // false :/ the new user fetched here actually has isLoggedIn === true but our this.user does not...
});
}, 2000);
}
}
如评论中所述,在某一点上,另一个自定义元素会UserService.login()
运行,UserService.user.isLoggedIn
会更改为true
(如果我{{1},这会反映在UserService
中} console.dir
},但其他this.user
' s CustomElement
不更新。
顺便说一下:this.user
中Promise.resolve()
的原因是将来会有服务器调用。
Tbh我对JS中的这种类型的编程很新,更多来自jQuery世界,尽管我基本上爱上了Aurelia这样的东西仍然让我很困惑,所以希望有一些洞察这里:))
答案 0 :(得分:2)
查看您提供的代码,我看不出会导致您所描述的行为的原因。
一个建议 - 让您的代码更易于管理,减少异步......如果您按照以下方式构建代码:
user.js的
export class User {
loggedIn = false;
name = 'Anonymous';
}
用户store.js
@inject(User)
export class UserStore {
constructor(user) {
this.user = user;
}
load() {
const serializedUser = localStorage.getItem('user');
if (!info) {
return;
}
const storageUser = JSON.parse(serializedUser);
this.user.loggedIn = storageUser.loggedIn;
this.user.name = storageUser.name;
}
save() {
const serializedUser = JSON.stringify(this.user);
localStorage.setItem('user', serializedUser);
}
}
AUTH-service.js
@inject(User, UserStore)
export class AuthService {
constructor(user, store) {
this.user = user;
this.store = store;
}
login(username, password) {
return fetch('https://api.megacorp.com/login', { method: 'POST' ... })
.then(result => {
this.user.loggedIn = true;
this.user.name = result.name;
this.store.save();
});
}
}
定制element.js
@inject(User)
export class CustomElement {
constructor(user) {
this.user = user;
}
...
}
您的自定义元素的好处永远不需要对异步的东西进行dep。他们只获取应用程序的User实例,其属性可能会更改,但始终保持相同的实例。