9

我不确定解决此问题的最佳方法:

我正在编写一个 Web 应用程序,它为许多“项目”对象实现了基本的 CRUD 功能。因此,用户可以创建他/她自己的一组项目。

我已经编写了一个用于添加/删除/列出项目的 REST API,并且我已经编写了一个 Reagent 前端客户端。如您所料,客户的项目保存在试剂原子(ratom)中。

这就是有趣的地方。

在我看过的所有教程中,它向您展示了如何更新 Ratom,您的 GUI 将自动更新。我有那个,那行得通。

我目前正在做的是,在更新客户端状态时,我进行 REST POST 调用以更新数据库上的服务器状态。

但是,这感觉不对。我现在将状态存储在两个地方:客户端和服务器上,两者都可能不同。

如果我将其实现为一个普通的旧网页,服务器将向客户端发送一个页面,其中包含数据库的最新状态。但是,状态已经存在于客户端上,我不知道应该如何同步它。

在初始 POST 成功后,我是否应该再次调用服务器(GET 请求)?这可以代替鼠尾草的内容。然后我提出了两个请求……这似乎很浪费。

或者是使用chordsente之类的东西来异步管理客户端状态的最佳实践。这会更好,因为这意味着来自其他用户的更改将在客户端立即刷新。但是,我看不到任何演示对其中任何一个做出反应的教程,所以也许我走错了路。

所以问题很简单,应该如何结合使用 REST?

谢谢

4

3 回答 3

3

我同意@myguidingstar 的观点,即您的问题更多是关于客户端-服务器同步,而不是关于 clojure 或试剂。你可能会遇到类似的问题,比如 GWT(去过那里,...)

在初始 POST 成功后,我是否应该再次调用服务器(GET 请求)?这可以代替鼠尾草的内容。然后我提出了两个请求……这似乎很浪费。

您似乎错过了 POST 请求也可以触发来自服务器的响应。

这里最大的问题是为什么您需要客户端上的数据库状态?您是否有迫使您最小化从服务器获取数据的 GET 请求数量的要求?或者您是否在不需要服务器交互的客户端(ClojureScript/reagent)端实现了业务逻辑?您还需要考虑同一问题的另一面:如果您的客户端状态在一段时间内没有更新是否可以,或者您是否会遇到一致性问题,因为“其他东西”正在修改您客户端后面的服务器上的数据背部?

最后,你说你

..不知道我应该如何同步它。

你的问题到底是什么?为什么不更新应用程序状态(swap! app-state update-in ...)在您从服务器获取数据之后,如试剂教程中所述?

于 2014-11-27T09:11:14.777 回答
2

这是一个关于客户端-服务器同步的大问题,大多数 Web 应用程序都在努力解决。

Tonsky 有一个图书馆可以解决这个问题:

https://github.com/tonsky/datascript

阅读他的博客文章和示例datascript-chat以了解设计。这需要很多学习,但恐怕这是唯一一种不是“感觉不对”的方法。

于 2014-11-27T01:50:11.847 回答
2

正如其他人所指出的,对于可能有多个客户端的任何客户端/服务器应用程序来说,这是一个常见的设计挑战。我认为关键在于仔细观察你需要在你的客户中保持什么样的状态。诸如“您的客户端是否真的需要有关服务器或远程数据库的最新状态信息,还是只需要有关客户端执行的操作的最新信息?例如,您需要知道什么是在更新后的远程数据库表中,还是您只需要知道您的更新是否成功?

我看到的另一件事可能会导致开发人员走上错误的道路,那就是过早地担心效率。为了提高效率,该设计有时会尝试在本地客户端中加入过多的状态,认为这会减少对远程服务器的调用次数并使应用程序响应更快。然而,通常你会得到一个过于复杂的实现,由于大量的本地状态管理开销而很难正确实现,通常包括大量仅在客户端接口的有限或不经常使用的部分中使用/相关的信息。接下来你知道的是,你的应用程序正在失去效率,因为它可以保持不需要的状态同步。

这里的挑战是由于我们倾向于以序列化的方式思考问题。这是很自然的。然而,这里的问题并不完全符合这种思维方式。系统的远程状态正在以不可预测的速度变化。即使您采用将更改推送到客户端的架构,您也会遇到与计算此类更改应该多久推送一次以及如何在界面中反映这些更改以使用户仍然获得一致和一致的问题相关的问题。有意义的图片。

我的方法只是众多方法之一,可能不是最理想的方法,它是按照与许多数据库客户端(在某种程度上甚至是 Clojure 自己的 STM)相同的方式对 Web 应用程序进行建模。客户端中的状态是特定时间点的远程状态的快照。它可能不准确或不是最新的,但它应该是一致的。当客户端提交更改时,它可能会成功也可能不会成功,这取决于自从我开始在客户端中输入更改后服务器中发生的更改。如果成功,则完全成功;如果失败,则完全失败。

正如其他人所指出的,这与 Reagent 没有直接关系。这是一个边界设计问题。但是,它可能会产生间接影响。例如,当您更新试剂原子时,您的试剂容器将被渲染。当原子被更新时它是知道的,但它不知道何时更新只是对现有信息的刷新而没有变化,所以你真的只想在它需要更新时更新原子,因为有些东西已经改变了。但是,除非这种情况非常频繁地发生并且您的组件非常复杂,否则即使您经常进行刷新类型更新,您也可能不会看到任何实际影响。

我会专注于将状态保持在最低限度并开发一个非常简单的设计,然后进行负载测试并确定是否存在性能问题并在出现问题时进行处理。

于 2014-11-29T21:13:21.313 回答