【问题标题】:How to get id of new item ngrx如何获取新项目ngrx的ID
【发布时间】:2018-08-05 23:16:15
【问题描述】:

我使用的格式是

{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所说那么将返回的数据发送到商店

所以我最终所做的是在 do 函数中调用 next 方法,并将其添加到进行 HTTP 调用的效果中,因此使用来自服务器的响应调用 next 方法

我也设置了监听socket的效果:

@Effect() watchSocket$ = this.socketService.socket$

当通过套接字发送操作时,它会分派更新状态的操作,但现在具有正确的有效负载。

在ngrx中实现websocket是一个学习曲线,例如,我最初使用watchSocket$效果来返回一个会进行HTTP调用的动作,然后调度一个动作来更新状态,

但是由于来自 watchSocket$ 的操作被分派给所有客户端,每个客户端都会尝试发出相同的 HTTP 请求,想象一下有 100 个客户端尝试删除相同的项目!

所以我分成2个效果一个来更新数据库(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)
            }
        })

【问题讨论】:

  • 通过 ADD_PRODUCT 和 ADD_PRODUCT_SUCCESS 等两个操作使用ngrx 效果,从服务器返回插入的对象,然后将其添加到存储中。

标签: angular mongodb ngrx


【解决方案1】:

所以你有两个动作:

ADD_PRODUCT_REQUESTED(带有效负载)

这里的有效负载是 POST 请求的主体(见下文)。 这第一个动作触发了一个效果,它向您的服务器发出后端 POST (CREATE) 请求。当后端请求完成时,效果会触发下面的第二个动作,将响应作为有效负载传递。 或者,第一个操作可能会在没有 ID 的情况下将数据插入到存储中,这样您就可以开始显示数据而无需等待 HTTP 请求完成。

ADD_PRODUCT_COMPLETED(带有效负载)

这会接收来自 effect 的有效负载,并使用相关 ID 在 store 中插入(或更新)数据。

PS 您可能还想考虑使用 ngrx/entity 来简化集合的使用。

你可能已经习惯了 action 和 reducer。如果你不熟悉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 请求。

【讨论】:

  • 谢谢你,它成功了,我已经编辑了我的问题,只是为了让事情更清楚我想要做什么,我做了什么,再次感谢
  • np - 仅供参考 - 这种方法取自 Udemy ngrx ng6 课程 - 让您知道这是解决问题的最佳方法
  • @danday74 如果在这里使用实体,他们将如何定义他们的 selectId 实现,因为 id 是在后端定义的?
猜你喜欢
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
相关资源
最近更新 更多