如何将不同HttpDataSource的多个Falcor模型合并为单一模型?
合并多数据源Falcor模型的解决方案
嘿,这个问题我刚好处理过,给你两种实用的方案,尤其是第一种直接基于你现有的两个模型来合并,非常贴合你的场景:
方案一:自定义组合DataSource(推荐)
核心思路是创建一个自定义的Falcor DataSource,内部持有你已有的user_model和role_model,然后根据请求的路径前缀(比如user或role),把请求转发到对应的模型,最后合并返回结果。这样你就能用一个统一的模型同时操作两个数据源的内容了。
第一步:实现自定义CombinedDataSource
class CombinedDataSource { constructor(userModel, roleModel) { this.userModel = userModel; this.roleModel = roleModel; } // 处理get请求,拆分路径转发到对应模型 get(pathSets) { // 筛选出属于user和role的路径集合 const userPaths = pathSets.filter(path => path[0] === 'user'); const rolePaths = pathSets.filter(path => path[0] === 'role'); const requestPromises = []; if (userPaths.length) { requestPromises.push(this.userModel.get(userPaths)); } if (rolePaths.length) { requestPromises.push(this.roleModel.get(rolePaths)); } // 合并两个模型的返回结果 return Promise.all(requestPromises) .then(results => { const combinedJsonGraph = {}; results.forEach(result => { Object.assign(combinedJsonGraph, result.jsonGraph); }); return { jsonGraph: combinedJsonGraph }; }); } // 处理set请求,拆分jsonGraph到对应模型 set(jsonGraph) { const userJsonGraph = {}; const roleJsonGraph = {}; if (jsonGraph.user) userJsonGraph.user = jsonGraph.user; if (jsonGraph.role) roleJsonGraph.role = jsonGraph.role; const requestPromises = []; if (Object.keys(userJsonGraph).length) { requestPromises.push(this.userModel.set(userJsonGraph)); } if (Object.keys(roleJsonGraph).length) { requestPromises.push(this.roleModel.set(roleJsonGraph)); } return Promise.all(requestPromises) .then(results => { const combined = { jsonGraph: {} }; results.forEach(res => Object.assign(combined.jsonGraph, res.jsonGraph)); return combined; }); } // 处理call请求,根据路径前缀转发 call(callPath, args, refSuffixes, thisPaths) { if (callPath[0] === 'user') { return this.userModel.call(callPath, args, refSuffixes, thisPaths); } else if (callPath[0] === 'role') { return this.roleModel.call(callPath, args, refSuffixes, thisPaths); } return Promise.reject(new Error(`Unsupported path prefix: ${callPath[0]}`)); } }
第二步:创建合并后的统一模型
// 初始化你原有的两个模型 const user_model = new falcor.Model({ source: new HttpDataSource('http://localhost:3000/api/userManagement') }); const role_model = new falcor.Model({ source: new HttpDataSource('http://localhost:3000/api/roleManagement') // 补全你的role数据源地址 }); // 创建合并后的模型 const combinedModel = new falcor.Model({ source: new CombinedDataSource(user_model, role_model) });
第三步:使用统一模型
现在你可以像操作单一模型一样,同时请求或修改两个数据源的数据:
// 同时获取用户列表和角色列表 combinedModel.get(['user', 'list'], ['role', 'list']) .then(result => { console.log('用户列表:', result.jsonGraph.user.list.value); console.log('角色列表:', result.jsonGraph.role.list.value); }); // 修改用户数据(会自动转发到user_model对应的数据源) combinedModel.set({ user: { list: { 0: { name: 'Updated Name' } } } });
方案二:使用Falcor Router作为中间层
如果你的场景允许,也可以搭建一个Falcor Router服务端,在Router里根据路径转发请求到不同的后端API(也就是你原来的两个HttpDataSource地址),然后前端只需要连接这个Router的数据源。不过这种方式需要额外搭建一个中间Router服务,适合需要对请求做更多统一处理的场景。
举个简单的Router示例:
// 服务端Router代码 const falcorExpress = require('falcor-express'); const Router = require('falcor-router'); const axios = require('axios'); const CombinedRouter = Router.createClass([ { route: 'user.list', get: () => { return axios.get('http://localhost:3000/api/userManagement/user/list') .then(res => { return { path: ['user', 'list'], value: res.data.users }; }); } }, { route: 'role.list', get: () => { return axios.get('http://localhost:3000/api/roleManagement/role/list') .then(res => { return { path: ['role', 'list'], value: res.data.roles }; }); } } ]); // 然后在express里挂载这个Router app.use('/api/combined', falcorExpress.dataSourceRoute(() => new CombinedRouter()));
前端只需要连接这个统一的Router数据源:
const combinedModel = new falcor.Model({ source: new HttpDataSource('http://localhost:3000/api/combined') });
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

