使用 Falcor 发送集合和呼叫请求

Posted

技术标签:

【中文标题】使用 Falcor 发送集合和呼叫请求【英文标题】:Sending set and call requests with Falcor 【发布时间】:2019-08-21 22:25:39 【问题描述】:

我一直在尝试使用 Falcor 模型从端口 3000 上的 react-client 发送 set 和 call-requests 到在端口 3001 上为路由器服务的 node.js 服务器。get-request 工作没有问题,但有设置和调用请求我刚刚收到内部服务器错误。

我尝试将正文解析器添加到服务器并将crossDomain:true 添加到客户端请求中,因为它解决了一些问题,但似乎这些不是原因。

然后我尝试将 set-request 分离到它自己的路由,但结果仍然相同。

老实说,我什至不确定是 falcor、客户端还是后端的问题。更令人困惑的是,get-request 工作得很好。

我注意到一些关于设置和调用请求的信息。当向服务器发送该类型的请求时,请求的查询对象为空。当向同一路由发送有效的 get-request 时,对象是这样的

 paths: '[["user","marisanity",["_id","games_length"]]]',
  method: 'get' 

我不知道这是否有帮助。

这是服务器端:

server.js

const express = require('express');
const config = require('config');
const app = express();

const FalcorServer = require('falcor-express');
const bodyParser = require('body-parser');

const userRouter = require('./src/routes/users');

if (!config.get('jwtPrivateKey')) 
    console.error('jwtPrivateKey is not defined, shutting down');
    process.exit(1);


app.use(bodyParser.urlencoded(extended: false));

app.use(function(req, res, next) 
    res.header("Access-Control-Allow-Origin", `http://localhost:3000`);
    res.header("Access-Control-Allow-Headers", "Authorization, X-Auth-Token, Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Credentials", "true");
    next();
);

app.use('/api/users/model.json', FalcorServer.dataSourceRoute((req) => userRouter(req)));

const port = process.env.PORT || 3001;
app.listen(port, () => console.log(`Listening on port $port`));

users.js

const userRepository = require('./../db/repositories/userRepository');
const Router = require('falcor-router');

let UserRouterBase = Router.createClass([


    
        route: "user[keys:username][keys:fields]",
        get: async function (pathSet) 
            const results = [];

            return await userRepository.findByUsername(pathSet.username).then(user => 
                if (user === null || user.games.length === 0) 
                    return (
                        path: ['users'],
                        value: "No results"
                    );
                 else 
                    pathSet.fields.forEach(field => 
                        if (field === 'games_length') 
                            results.push(
                                path: ['user', pathSet.username[0], "games_length"],
                                value: user.games.length
                            );
                         else 
                            results.push(
                                path: ['user', pathSet.username[0], field],
                                value: String(user[field])
                            );
                        
                    );
                    return results;
                
            )
        ,
        async set(jsonGraphArg) 

            console.log(jsonGraphArg);

            return 
                path: ['user', 'marisanity', 'games_length'],
                value: 'test'
            ;
        
    
]);

let UserRouter = function (res) 
    UserRouterBase.call(this);
    //used later to pass token for this component
    this.res = res;
;

UserRouter.prototype = Object.create(UserRouterBase.prototype);

module.exports = function (res) 
    return new UserRouter(res);
;

这是客户端:

import React, Component from 'react';
import Falcor from 'falcor';
import HttpDataSource from 'falcor-http-datasource';

export default class Test extends Component 
    constructor(props) 
        super(props);

        this.userModel = this.constructUserModel();
    

    componentDidMount() 
        //works just fine
        this.fetchUserInfo();


        //this produces error
        this.editUSerInfo();

    

    constructUserModel = () => 
        return new Falcor.Model(
            source: new HttpDataSource('http://localhost:3001/api/users/model.json', 
                crossDomain: true,
                headers: 
                    'x-auth-token': "secret"
                
            )
        );
    ;


    editUSerInfo = () => 
        this.userModel.setValue(["user", "marisanity","games_length"], 3).then(function(done)
            console.log(done);
        );
    ;

    fetchUserInfo = () => 
        this.userModel.get(["user", ['marisanity'], ['_id', 'games_length']])
            .then(function (response) 
                console.log(response);
            );
    ;

最后这是浏览器中显示的错误:

OPTIONS http://localhost:3001/api/users/model.json 500 (Internal Server Error)
requestObserver @   request.js:135
o.subscribe @   request.js:30
sendSetRequest  @   sendSetRequest.js:41
set @   RequestQueueV2.js:40
setRequestCycle @   setRequestCycle.js:63
_subscribe  @   SetResponse.js:89
subscribe   @   ModelResponse.js:90
(anonymous) @   setValue.js:25
subscribe   @   ModelResponse.js:90
(anonymous) @   ModelResponse.js:137
then    @   ModelResponse.js:134
Test._this.editUSerInfo @   Wow.js:55
componentDidMount   @   Wow.js:18
commitLifeCycles    @   react-dom.development.js:18071
commitAllLifeCycles @   react-dom.development.js:19630
callCallback    @   react-dom.development.js:147
invokeGuardedCallbackDev    @   react-dom.development.js:196
invokeGuardedCallback   @   react-dom.development.js:250
commitRoot  @   react-dom.development.js:19854
(anonymous) @   react-dom.development.js:21402
unstable_runWithPriority    @   scheduler.development.js:255
completeRoot    @   react-dom.development.js:21401
performWorkOnRoot   @   react-dom.development.js:21324
performWork @   react-dom.development.js:21229
performSyncWork @   react-dom.development.js:21203
requestWork @   react-dom.development.js:21058
scheduleWork    @   react-dom.development.js:20871
scheduleRootUpdate  @   react-dom.development.js:21566
updateContainerAtExpirationTime @   react-dom.development.js:21592
updateContainer @   react-dom.development.js:21660
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @   react-dom.development.js:21973
(anonymous) @   react-dom.development.js:22125
unbatchedUpdates    @   react-dom.development.js:21448
legacyRenderSubtreeIntoContainer    @   react-dom.development.js:22121
render  @   react-dom.development.js:22196
./src/index.js  @   index.js:7
__webpack_require__ @   bootstrap:781
fn  @   bootstrap:149
0   @   Yay.js:4
__webpack_require__ @   bootstrap:781
checkDeferredModules    @   bootstrap:45
webpackJsonpCallback    @   bootstrap:32
(anonymous)

【问题讨论】:

尝试使用 Express 的官方 CORS 中间件,而不是自己动手:expressjs.com/en/resources/middleware/cors.html。抛出的错误表明 OPTIONS 预检请求出错,因此这将与 Falcor 正交 查看 MDN 文档:developer.mozilla.org/en-US/docs/Web/HTTP/CORS。并非所有跨源请求都需要预检 OPTIONS 请求,这可能是您的 GET 请求有效的原因,而不是您的 SET 或 CALL 请求 非常感谢!你又解决了我的问题。从现在开始肯定会使用 Express 的官方 cors 中间件 :D 太棒了!如果你有时间,写下你的问题的答案并接受它,这样问题就可以被标记为已回答。 【参考方案1】:

此问题是由无效的 CORS 配置引起的。通过用 Express 的官方 CORS 中间件替换旧配置解决了这个问题:

const cors = require('cors');

const corsOptions = 
    origin: 'http://localhost:3000',
    credentials: true,
    optionsSuccessStatus: 200
;

app.use(cors(corsOptions));

【讨论】:

以上是关于使用 Falcor 发送集合和呼叫请求的主要内容,如果未能解决你的问题,请参考以下文章

Netflix Falcor - 何时从数据源返回 pathValues 与 jsonGraph?

协议集合

将 falcor 用于具有瞬态数据的多参数请求

postman怎么发送post请求

个人技术总结——postman的使用(使用数据变量多次运行集合)

在Postman脚本中发送请求(pm.sendRequest)