ReactJS商店订单

时间:2015-08-27 12:44:05

标签: reactjs reactjs-flux flux

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

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

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

2 个答案:

答案 0 :(得分:2)

我认为你不应该执行同步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_RECEIVED之类的操作。 AuthStore将通过更新其内部token状态来响应此操作,以存储收到的token,以便下次我们需要时,我们不需要再进行另一次ajax调用。然后,AuthStore发出更改。

全部放在一起:

状态1:用户首次点击页面

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

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

    状态2:在令牌

    之前接收动态数据

    因为我们运行异步请求所以完全合理。让我们看看会发生什么:

    1. 动态数据的ajax请求会解析并触发FOO_DATA_RECEIVED操作。
    2. FooStore通过更新其内部状态以包含接收的数据来响应此操作。
    3. FooStore发出更改
    4. AuthStore.getToken()已经处于待处理状态,因此我们什么都不做(这可以通过Promise完成,但不在此问题的范围内)
    5. FooStore.getAll()现在返回提取的数据
    6. 由于我们没有令牌,因此
    7. PageWithDynamicData呈现与之前完全相同。
    8. 发生相同的渲染:

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

      状态3:我们收到令牌

      1. 从服务器获取请求会解析并触发操作TOKEN_RECEIVED
      2. AuthStore通过使用收到的令牌更新其内部状态并发出更改来响应此操作
      3. PageWithDynamicData收到更改,对AuthStore.getToken()FooStore.getAll()的调用现在返回正确的数据
      4. PageWithDynamicData现在呈现数据:
      5. 该页面现在将数据呈现给经过身份验证的用户:

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

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

答案 1 :(得分:0)

您需要确保令牌的请求是&#34;同步&#34;与默认&#34;异步&#34;。在测试时,我使用jQuery进行XHR调用,并遇到了类似的情况。 jQuery有一个属性,你可以设置同步调用,它会在进一步执行代码之前等待结果。

<强>更新

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

这可能需要一些修改,这是我的头脑。如果您打算使用jQquery,请参阅以下文档:jQuery Ajax