在同构通量应用程序中,是不是应该在操作中实现 REST api 调用?

Posted

技术标签:

【中文标题】在同构通量应用程序中,是不是应该在操作中实现 REST api 调用?【英文标题】:In an isomorphic flux application, should the REST api calls be implemented in the action?在同构通量应用程序中,是否应该在操作中实现 REST api 调用? 【发布时间】:2016-01-25 15:08:05 【问题描述】:

应该在动作创建器中实现,还是在服务类或组件中实现?如果是同构 Web 应用,推荐是否会改变?

我见过两个不同的例子:

    动作创建者在进行其余调用后调度一个动作 login_success/login_failure 组件首先调用 api 服务,该服务直接创建 login_success 或 failure 操作

示例 1

https://github.com/schempy/react-flux-api-calls

/actions/LoginActions.js

动作本身触发对 api 的调用,然后分派成功或失败

var LoginActions = 
    authenticate: function () 
        RESTApi
            .get('/api/login')
            .then(function (user) 
                   AppDispatcher.dispatch(
                     actionType: "login_success",
                     user: user
                   );
            )
            .catch(function(err) 
                   AppDispatcher.dispatch(actionType:"login_failure");
            );
    ;
;

示例 2

https://github.com/auth0/react-flux-jwt-authentication-sample

组件 onclick 调用一个 authservice 函数,然后在它返回认证结果后创建一个动作

/services/AuthService.js

class AuthService 

  login(username, password) 
    return this.handleAuth(when(request(
      url: LOGIN_URL,
      method: 'POST',
      crossOrigin: true,
      type: 'json',
      data: 
        username, password
      
    )));
  

  logout() 
    LoginActions.logoutUser();
  

  signup(username, password, extra) 
    return this.handleAuth(when(request(
      url: SIGNUP_URL,
      method: 'POST',
      crossOrigin: true,
      type: 'json',
      data: 
        username, password, extra
      
    )));
  

  handleAuth(loginPromise) 
    return loginPromise
      .then(function(response) 
        var jwt = response.id_token;
        LoginActions.loginUser(jwt);
        return true;
      );
  

这个调用在 Flux 架构中的更好/标准位置是什么?

【问题讨论】:

【参考方案1】:

我使用带有 api 实用程序的 api.store。来自https://github.com/calitek/ReactPatternsReact.14/ReFluxSuperAgent。

import Reflux from 'reflux';

import Actions from './Actions';
import ApiFct from './../utils/api.js';

let ApiStoreObject = 
	newData: 
		"React version": "0.14",
		"Project": "ReFluxSuperAgent",
		"currentDateTime": new Date().toLocaleString()
	,
	listenables: Actions,
	apiInit()  ApiFct.setData(this.newData); ,
	apiInitDone()  ApiFct.getData(); ,
	apiSetData(data)  ApiFct.setData(data); 

const ApiStore = Reflux.createStore(ApiStoreObject);
export default ApiStore;

import request from 'superagent';

import Actions from '../flux/Actions';

let uri = 'http://localhost:3500';

module.exports = 
	getData()  request.get(uri + '/routes/getData').end((err, res) =>  this.gotData(res.body); ); ,
	gotData(data)  Actions.gotData1(data); Actions.gotData2(data); Actions.gotData3(data); ,
	setData(data)  request.post('/routes/setData').send(data).end((err, res) =>  Actions.apiInitDone(); ) ,
;

【讨论】:

【参考方案2】:

根据我的经验,最好使用选项 1:

将 API 调用放在动作创建者而不是组件中可以让您更好地分离关注点:您的组件 (-tree) 只调用“登录”动作,并且可能不知道响应来自何处。如果登录详细信息已知,理论上可能来自商店。 对 API 的调用在操作中更加集中,因此更易于调试。

选项 2 看起来仍然符合通量设计原则。

还有第三种选择的倡导者:从商店调用 webAPI。这使得服务器端和客户端数据结构的紧密耦合更容易/更有条理。如果在客户端和服务器之间同步独立数据结构是一个关键问题,可能会更好。我对第三种选择的经验并不乐观:让商店(间接)创建操作打破了单向通量模式。对我的好处永远不会超过调试中的额外麻烦。但您的结果可能会有所不同。

【讨论】:

以上是关于在同构通量应用程序中,是不是应该在操作中实现 REST api 调用?的主要内容,如果未能解决你的问题,请参考以下文章

没有通量的同构 react.js

在同构 reactjs 中检测移动设备

关于通量约定,为啥每个操作只有一个文件?

为啥认证应该在过滤器而不是控制器中实现?

如何在 Flutter 中实现应用栏操作文本而不是操作图标?

同构 JS - 仅限 httpRequest 客户端