【问题标题】:ReactJS Stores orderReactJS 存储顺序
【发布时间】:2015-11-21 20:34:21
【问题描述】:

我有一个商店——我们称之为AuthStore——它包含一个身份验证脚本并保留令牌,这是所有 API 请求的重要参数。所以我需要的是在任何其他商店请求令牌之前触发身份验证脚本并存储令牌。

如果在webapp 加载时检索到令牌,我的代码就可以工作。但如果用户看到的第一个页面是需要另一个商店加载动态数据的页面,那么有时其他商店会在AuthStore 实际拥有令牌之前从AuthStore 请求令牌。

如何避免这种情况,并确保令牌在其他商店请求之前存在?

【问题讨论】:

    标签: reactjs reactjs-flux flux


    【解决方案1】:

    我认为你不应该执行同步 AJAX 调用。

    我不知道你的具体实现细节,但让我们想象一下,我们遇到了page/with/dynamic/data 需要身份验证:

    var getStateFromStores = function() {
        return {
            authToken: AuthStore.getToken(),
            dynamicData: FooStore.getAll()
        }
    }
    
    var PageWithDynamicData = React.createClass({
    
        getInitialState: function() {
            return getStateFromStores();
        },
    
        componentDidMount: function() {
            AuthStore.addChangeEventListener(this._onChange);
            FooStore.addChangeEventListener(this._onChange);
        },
    
        componentWillUnmount: function() {
            AuthStore.removeChangeEventListener(this._onChange);
            FooStore.removeChangeEventListener(this._onChange);
        },
    
        render: function() {
    
            if (!authToken || dynamicData.length == 0) {
                return (
                    <p>Loading</p>
                )
            }
    
            if (dynamicData.length == 0) { //we could be authenticated but dynamic datas are not retrievied yet
                return (
                    <p>Loading</p>
                )
            }
    
            return dynamicData.map(function (data) {
                return <Foo data={data}/>
            });
    
        }
    
        _onChange: function() {
            this.setState(getStateFromStores());
        }
    
    });
    

    AuthStore 可能应该将token 存储在其缓存中,并在第一次调用AuthStore.getToken() 时通过ajax 调用检索它。当这个 ajax 调用解析时,它会触发一个动作,例如TOKEN_RECEIVEDAuthStore 将通过更新其内部token 状态来响应此操作以存储收到的token,因此下次我们需要它时,我们不需要再进行一次ajax 调用。然后,AuthStore 发出变化。

    把它们放在一起:

    状态1:用户第一次点击页面

    1. 用户点击page/with/dynamic/data
    2. 您的PageWithDynamicData 通过getStateFromStores 获取其初始状态
    3. AuthStore.getToken() 被调用,此时它没有任何令牌,所以他触发了一个 ajax 调用(可能通过一些 WebAPIUtils 模块)来检索它(异步)。
    4. FooStore.getAll() 被调用。同样,缓存中没有数据,因此调用 API 以检索数据(异步)。
    5. 由于缺少this.state.authTokenthis.state.dynamicDataPageWithDynamicData 呈现在其加载状态

    例子:

    ++++++++++++++++++++++
    +                    +
    +     "loading"      +
    +                    +
    ++++++++++++++++++++++
    

    状态2:在token之前收到动态数据

    这是完全合理的,因为我们运行的是异步请求。让我们看看会发生什么:

    1. 动态数据的 ajax 请求解析并触发 FOO_DATA_RECEIVED 操作。
    2. FooStore 通过更新其内部状态以包含接收到的数据来响应此操作。
    3. FooStore 发出变化
    4. AuthStore.getToken() 已经挂起,所以我们什么也不做(这可以通过 Promise 完成,但这超出了这个问题的范围)
    5. FooStore.getAll() 现在返回获取的数据
    6. PageWithDynamicData 的渲染与之前完全相同,因为我们没有令牌。

    出现同样的渲染:

    ++++++++++++++++++++++
    +                    +
    +     "loading"      +
    +                    +
    ++++++++++++++++++++++
    

    状态 3:我们收到令牌

    1. 从服务器获取的请求解析并触发操作TOKEN_RECEIVED
    2. AuthStore 通过使用接收到的令牌更新其内部状态并发出更改来响应此操作
    3. PageWithDynamicData 接收更改并且对 AuthStore.getToken()FooStore.getAll() 的调用现在返回正确的数据
    4. PageWithDynamicData 现在呈现数据:

    页面现在将数据呈现给经过身份验证的用户:

    ++++++++++++++++++++++
    +                    +
    +  - "some data"     +
    +  - "another one"   +
    +  - "..."           +
    +                    +
    ++++++++++++++++++++++
    

    重要提示:这不是“如何在我的 React 应用程序中处理身份验证”的答案,因为在这种情况下,我们可能应该使用一些会话存储或其他什么。但这里的重点是展示我们如何“等待”某事发生,然后再做任何其他事情,这要归功于 Flux 来保持单向数据流。

    【讨论】:

      【解决方案2】:

      您需要确保对令牌的请求是“同步”而不是默认的“异步”。在测试时,我使用 jQuery 进行 XHR 调用并遇到了类似的情况。 jQuery 有一个属性,您可以为同步调用设置该属性,该属性将在进一步执行代码之前等待结果。

      更新

      function xhr() {
          return $.ajax({
              type: "GET",
              url: "/url/to/data/here",
              async: false
          }).responseText;
      }
      

      这可能需要一些修改,它是我的头顶。如果您打算使用 jQquery,这里是文档:jQuery Ajax

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-22
        • 2021-08-27
        • 1970-01-01
        • 1970-01-01
        • 2015-10-29
        • 2011-03-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多