我使用的格式是
{product._id:{product._id:string, product_name:string}, product._id:{product._id:string, product_name:string}}
保存我的商店的产品信息
一切正常,在加载时我用以下方法进行设置:
function handleBlogsLoadedAction(state, action) {
const returnedBlogs = action.payload
const blogObj = returnedBlogs.reduce(
(blogs: { [id: string]: Blog }, blog: Blog) =>
{
return Object.assign(blogs, { [blog._id]: blog });
}, {});
let newState = Object.assign({}, state);
newState = {
loaded:true,
blogs:blogObj
}
return newState;
}
所以我最终得到这样的东西:
{"12345":{product._id:"12345", product_name:"product1"}, "6789":{product._id:"6789", product_name:"product2"}}
我可以对其进行更新和删除,但是在添加时,问题是创建后获取ID的最佳方法,这样我就可以插入状态
问题是我不想自己生成id,数据库必须这样做
有人知道最佳实践吗,或者只是对如何实现有一些想法
编辑:
我很抱歉,这个问题比上面说明的要复杂一些。
@ danday74的回答是正确的答案,但我提出的问题很差,我认为我应该分享和阐述,以期希望能帮助其他人。
我的商店还使用websocket与其他客户端通信,@Effect() beginUpdate$
监听操作:
BLOG_UPDATE_START_ACTION, BLOG_DELETE_START_ACTION, BLOG_ADD_START_ACTION
在触发beginUpdate $时,将为套接字主题调用下一个方法
this.socketService.socket$.next(JSON.stringify(action))
哪个动作执行/发送到连接的客户端,然后从beginUpdate $分派一个动作来更新数据库。
您可以看到问题在这里发展,我需要按照@ danday74的说明更新数据库 THEN 将返回的数据分派到商店
最后,我所做的是在do函数中进行了下一个方法调用,并将其添加到进行HTTP调用的效果中,因此使用服务器的响应来调用next方法。
我还设置了一种监听套接字的效果:
@Effect()watchSocket $ = this.socketService.socket $
通过套接字发送动作时,它会分派更新状态但现在具有正确有效负载的动作。
这是将websocket实施到ngrx的学习过程,例如,我最初是使用watchSocket $效果返回一个将进行HTTP调用的操作,然后调度一个操作以更新状态,
但是由于watchSocket $中的操作已分派给所有客户端,因此每个客户端都将尝试发出相同的HTTP请求,假设有100个客户端尝试删除同一项目!
所以我分成了两种效果来更新数据库(HTTP请求)
哪个响应发送到套接字,套接字将更新所有连接的存储。
如果有人可以对最佳做法提出任何建议,请放心
//Effects that make HTTP requests
@Effect({dispatch:false}) updateDB$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogUpdateDBAction>(fromBlogActions.BLOG_UPDATE_DB_ACTION)
.mergeMap(action => {
console.log(action)
return this.blogService.updateBlog(action.payload.blog)
})
.do((blog:Blog)=> this.socketService.socket$.next(JSON.stringify({type:fromBlogActions.BLOG_UPDATE_START_ACTION, payload:{blog:blog}})))
@Effect({dispatch:false}) deleteBlogFromDB$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogDeleteDBAction>(fromBlogActions.BLOG_DELETE_DB_ACTION)
.mergeMap(action => {
console.log(action)
return this.blogService.deleteBlog(action.payload.blog)
})
.do((blog:Blog)=> this.socketService.socket$.next(JSON.stringify({type:fromBlogActions.BLOG_DELETE_START_ACTION, payload:{blog:blog}})))
@Effect({dispatch:false}) addBlogToDB$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogAddToDBAction>(fromBlogActions.BLOG_ADDED_TO_DB_ACTION)
.mergeMap(action => {
console.log(action)
return this.blogService.addBlog(action.payload.blog)
.catch(()=>{
return Observable.of({})
})
})
.do((blog:Blog)=> this.socketService.socket$.next(JSON.stringify({type:fromBlogActions.BLOG_ADD_START_ACTION, payload:{blog:blog}})))
// Effects to update state
@Effect() deleteBlog$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogDeletedAction>(fromBlogActions.BLOG_DELETED_ACTION)
.map((action)=>new fromBlogUIActions.CrudSucessAction(action))
@Effect() updateBlog$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogUpdatedAction>(fromBlogActions.BLOG_UPDATED_ACTION)
.map((action)=>new fromBlogUIActions.CrudSucessAction(action))
@Effect() addBlog$: Observable<any> = this.actions$
.ofType<fromBlogActions.BlogAddedAction>(fromBlogActions.BLOG_ADDED_ACTION)
.map((action)=>new fromBlogUIActions.CrudSucessAction(action))
// Updates Database (CRUD)
@Effect() beginUpdate$: Observable<Action> = this.actions$
.ofType(fromBlogActions.BLOG_UPDATE_START_ACTION, fromBlogActions.BLOG_DELETE_START_ACTION, fromBlogActions.BLOG_ADD_START_ACTION)
.map((action:any)=>{
//Update database, but doing it here makes sure it's only done once
if (action.type === fromBlogActions.BLOG_UPDATE_START_ACTION) {
return new fromBlogActions.BlogUpdateDBAction(action.payload);
}
if (action.type === fromBlogActions.BLOG_DELETE_START_ACTION) {
return new fromBlogActions.BlogDeleteDBAction(action.payload);
}
if (action.type === fromBlogActions.BLOG_ADD_START_ACTION) {
return new fromBlogActions.BlogAddToDBAction(action.payload);
}
})
// Watches websocket
@Effect() watchSocket$:Observable<any> = this.socketService.socket$
.map((action : any) => {
//Update state across clients
if (action.type === fromBlogActions.BLOG_UPDATE_START_ACTION) {
return new fromBlogActions.BlogUpdatedAction(action.payload)
}
if (action.type === fromBlogActions.BLOG_DELETE_START_ACTION) {
return new fromBlogActions.BlogDeletedAction(action.payload)
}
if (action.type === fromBlogActions.BLOG_ADD_START_ACTION) {
return new fromBlogActions.BlogAddedAction(action.payload)
}
})
答案 0 :(得分:3)
因此,您有两个操作:
ADD_PRODUCT_REQUESTED(带有有效负载)
此处的有效负载是POST请求的主体(请参见下文)。 第一个动作触发一个效果,该效果向您的服务器发出后端POST(CREATE)请求。后端请求完成后,效果将触发下面的第二个动作,将响应作为有效负载传递。 (可选)该第一个操作可以将没有ID的数据插入到存储中,以便您可以开始显示数据而无需等待HTTP请求完成。
ADD_PRODUCT_COMPLETED(带有有效负载)
这将从效果中接收有效载荷,并将具有相关ID的数据插入(或更新)商店中的数据。
PS您可能还需要考虑使用ngrx / entity来简化集合的工作。
您可能习惯了采取行动和简化措施。如果您不熟悉ngrx / effects,这里有一些示例代码可以完成这种事情:
@Effect()
allFiltersRequested$ = this.actions$.pipe(
ofType<BimRequestedAction>(BimsActionTypes.BimRequested),
tap((action) => debug(action)),
mergeMap((action) =>
// essential to catchError else an HTTP error response will disable this effect
this.bimService.getBim(action.payload).pipe(
catchError(() => {
return of({})
})
)
),
map((bim) => new BimLoadedAction(bim))
)
bimService正在发出HTTP请求。