我使用的格式是
{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))
它携带/发送 Action 到连接的客户端,然后从 beginUpdate$ 分派(dispatch)一个 Action 来更新数据库。
您可以看到这里出现的问题,我需要按照@danday74 所述更新数据库然后将返回的数据发送到商店
所以最后我所做的是调用下一个方法调用,它在一个 do 函数中,并将它添加到进行 HTTP 调用的效果中,所以下一个方法是用服务器的响应调用的
我还设置了监听socket的效果:
@Effect() watchSocket$ = this.socketService.socket$
当通过套接字发送操作时,它会分派(dispatch)更新状态的操作,但现在具有正确的负载。
将 websocket 实现到 ngrx 是一个学习曲线,例如,我最初使用 watchSocket$ 效果返回一个将进行 HTTP 调用的操作,然后分派(dispatch)一个操作来更新状态,
但是因为来自 watchSocket$ 的操作被分派(dispatch)给所有客户端,所以每个客户端都会尝试发出相同的 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)
}
})
最佳答案
所以你有两个 Action :
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 请求。
关于angular - 如何获取新项目ngrx的id,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51698944/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为