使用 Flux 时保持 UI 与 ajax 调用同步的惯用方法是啥?

Posted

技术标签:

【中文标题】使用 Flux 时保持 UI 与 ajax 调用同步的惯用方法是啥?【英文标题】:What's the idiomatic way to keep UI in sync with ajax calls when using Flux?使用 Flux 时保持 UI 与 ajax 调用同步的惯用方法是什么? 【发布时间】:2015-09-16 11:35:15 【问题描述】:

一般问题:假设我有一个带有 onClick 处理程序的按钮调用动作创建者。该操作执行一个 ajax 调用,该调用在 ajax 响应时分派一条消息,这在某种程度上会影响 UI。鉴于这种基本模式,没有什么可以阻止用户多次单击此按钮,从而多次运行 ajax 调用。

React 或 Flux 文档中似乎没有提到这一点(据我所知),所以我尝试自己想出一些方法。

这里是那些方法

在执行 ajax 调用的方法上使用 lodash.throttle,以便快速连续多次单击不会创建多个调用。 在方法上使用 lodash.debounce,这样 ajax 只会在用户暂时没有进行任何活动时被调用。这就是我在更改时对文本字段进行半实时更新的方式。 在首次调用操作时向存储发送“正在更新”消息,然后在 ajax 调用返回时发送“完成”消息。执行一些操作,例如在初始消息上禁用输入,然后在第二个消息上重新启用。

就功能而言,第三种方法似乎是最好的,因为它允许您使用户界面准确地反映正在发生的事情,但它也非常冗长。它用大量额外的状态、处理程序方法等把所有东西都搞得一团糟......

我觉得这些方法中的任何一种都不是真正地道的。是什么?

【问题讨论】:

没有使用flux,但是你可以保留一个在ajax请求开始时设置为true的布尔标志变量,然后在回调中将它设置回false。在开始另一个请求之前在 onClick 测试该标志? 【参考方案1】:

我认为第三种方法是正确的方法,但我认为它并不冗长。我看到的很多 React 代码都错过了 React 的精神,即非常小的、可组合的组件。当创建大型单体组件时,是的,事情会变得非常混乱。

但是如果有问题的按钮是它自己的组件,那么它可以根据它的状态来处理渲染。当用户单击按钮时,该组件的状态会发生变化——并且它会以无法再次单击的方式呈现它。

一旦商店通知该组件它已更改,该组件就可以将其状态设置回 - 并使用它重新渲染自身。

这是一个非常简单的过程;它只需要将页面视为小型、可组合单元的集合。

【讨论】:

【参考方案2】:

Hal 非常正确。分派多条消息是最灵活的方式。

但是,我会谨慎发送IS_UPDATING 消息。这使得对代码的推理变得更加困难,因为对于每个 AJAX 操作,您会同时调度多个操作。

惯用的解决方案是将您的 AJAX“操作”(action-creator-actions)拆分为三个已调度的操作:MY_ACTIONMY_ACTION_SUCCESSMY_ACTION_FAILURE,适当处理每个实例,并跟踪“待处理”一路走来。

例如:

// MyActionCreator.js

// because this is in a closure, you can even use the promise 
// or whatever you want as a sort of "ID" to handle multiple
// requests at one time.
postMessage() 
    dispatch('POST_MESSAGE',  ...  );
    api.slowMessagePostingAjaxThingy().then(
        (success) =>  dispatch('POST_MESSAGE_SUCCESS',  ... ); ,
        (failure) =>  dispatch('POST_MESSAGE_FAILURE',  ... ); 
    );


// MyStore.js

on('POST_MESSAGE', (payload) =>  /* do stuff */ );
on('POST_MESSAGE_SUCCESS', (payload) =>  /* handle success */ );
on('POST_MESSAGE_FAILURE', (payload) =>  /* handle failure */ );

与其他解决方案相比,这为您提供了多项优势:

    您的商店完全可以控制商品是否处于待处理状态。您不必担心更改 UI 代码中的操作的 UI 状态:您可以让您的 UI 专门查看您商店的 pending 属性以获得真相。这可能是在 MVC 系统上使用 Flux 的最大原因。 您有一个干净的界面来执行您的操作。很容易推理并且很容易将其他商店附加到此数据(如果您有 LatestMessageStore 或其他东西,订阅这些事件很容易)。这是 Hal 建议的使用 IS_UPDATING 的好处。 在语义上有意义时保存 lodash 调用,例如当您可能被合法数据(文本字段)淹没时。 您可以轻松地在乐观更新(调用POST_MESSAGE 时更改存储)或悲观更新(更改POST_MESSAGE_SUCCESS 上的存储)之间切换。

【讨论】:

以上是关于使用 Flux 时保持 UI 与 ajax 调用同步的惯用方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Webflux(Mono/Flux) 与 AOP 在拦截时触发 REST 调用并使用 Mono/Flux

商店中的 Flux ajax api 调用返回父函数

Flux 中的 AJAX:依赖状态更改时刷新存储

reactjs/flux:按顺序执行动作(ajax)

在 React Flux 中进行 Ajax 调用的位置

WebView 与 react-native-router-flux NavBar 一起使用,但不适用于 sayem/ui NavigationBar