如何从服务器端 express/mongo/mongoose 中的 URL,客户端的 axios/react/redux 中获取参数 ID

Posted

技术标签:

【中文标题】如何从服务器端 express/mongo/mongoose 中的 URL,客户端的 axios/react/redux 中获取参数 ID【英文标题】:How to Get Param Id from URL in express/mongo/mongoose on server side, axios/react/redux on client side 【发布时间】:2018-09-12 05:44:50 【问题描述】:

我在从 url 获取参数时遇到了一些麻烦。我在服务器端使用 Express(4.16.3),并使用 Axios 发出请求。但我似乎无法从 Express 中的 url 获取参数。

这是我的代码:

在 Express 中的 Route.js 上

app.get('/api/surveys/:surveyId', (req, res, next) => 
    var id = req.params.surveyId;
    console.log(req.params);
    // it gets  params surveyId: ':surverId'
    res.send('Hello World');
);

所以它不会获取实际的 ID,而是记录参数:surveyId: ':surveyId'。我一直在研究,但似乎这是正确的方法。我也使用 axios 发出请求:

在 actions/index.js 中(我使用 react):

export const fetchOneSurvey = () => async dispatch => 
const res = await axios.get('/api/surveys/:surveyId');

dispatch( type: FETCH_ONE_SURVEY, payload: res.data );;

不确定这是否相关: 在视图页面上,我在 React 中设置了 http://localhost:3000/surveys/:surveyId 路由,而不是 http://localhost:3000/api/surveys/:surveyId。当我转到http://localhost:3000/surveys/:surveyId 时,它会像我在 express 中写的那样执行控制台日志 (req.params),但我只得到一个字符串 ':surveyId' 是参数,而不是 url 上的实际 id。

请任何人都可以帮助我?我尝试了许多不同的方法,但似乎没有任何效果。我提前非常感谢大家。

===== 额外部分 ====== 这是我的 index.js:

const express = require('express');
const mongoose = require('mongoose');
const cookieSession = require('cookie-session');
const passport = require('passport');
const bodyParser = require('body-parser');
const keys = require('./config/keys');

require('./models/User');
require('./models/Survey');
require('./services/passport');

mongoose.connect(keys.mongoURI);

const app = express();

app.use(bodyParser.json());
app.use(
    cookieSession(
        maxAge: 30 * 24 * 60 * 60 * 1000,
        keys: [keys.cookieKey]
    )
);

app.use(passport.initialize());
app.use(passport.session());

require('./routes/authRoutes')(app);
require('./routes/billingRoutes')(app);
require('./routes/surveyRoutes')(app);

if (process.env.NODE_ENV === 'production') 
    app.use(express.static('client/build'));

    const path = require('path');
    app.get('*', (req, res) => 
        res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
    );

我的调查模型路线js:

const _ = require('lodash');
const Path = require('path-parser');
const  URL  = require('url');
const mongoose = require('mongoose');
const requireLogin = require('../middlewares/requireLogin');
const requireCredits = require('../middlewares/requireCredits');
const Mailer = require('../services/Mailer');
const surveyTemplate = require('../services/emailTemplates/surveyTemplate');

const Survey = mongoose.model('surveys');

module.exports = app => 
    app.get('/api/surveys', requireLogin, async (req, res) => 
        const surveys = await Survey.find( _user: req.user.id ).select(
            recipients: false
        );

    res.send(surveys);
);

app.get('/api/surveys/:surveyId/:choice', (req, res) => 
    res.send('thanks for voting');
);

app.get('/api/surveys/:surveyId', (req, res, next) => 
    var id = req.params.surveyId;
    console.log(id);
    // it gets  params surveyId: ':surverId'
    res.send('Hello World');
);

app.post('/api/surveys/webhooks', (req, res) => 
    // console.log(req.body);
    // res.send();
    const p = new Path('/api/surveys/:surveyId/:choice');

    const test = _.chain(req.body)
        .map(( email, url ) => 
            const match = p.test(new URL(url).pathname);
            if (match) 
                return 
                    email,
                    surveyId: match.surveyId,
                    choice: match.choice
                ;
            
        )
        .compact()
        .uniqBy('email', 'surveyId')
        .each(( surveyId, email, choice ) => 
            Survey.updateOne(
                
                    // have to add _ to keys as mongoDB rule, mongoose doensn't need.
                    _id: surveyId,
                    recipients: 
                        $elemMatch:  email: email, responded: false 
                    
                ,
                
                    $inc:  [choice]: 1 ,
                    $set:  'recipients.$.responded': true ,
                    lastResponded: new Date()
                
            ).exec();
        )
        .value();

    console.log(test);

    res.send();
);

app.post('/api/surveys', requireLogin, requireCredits, async (req, res) => 
    const  title, subject, body, recipients  = req.body;

    const survey = new Survey(
        // map(email => ( email ) === map(email => return email: email)
        title,
        body,
        subject,
        recipients: recipients
            .split(',')
            .map(email => ( email: email.trim() )),
        _user: req.user.id,
        dateSent: Date.now()
    );

    // send an email
    const mailer = new Mailer(survey, surveyTemplate(survey));
    try 
        await mailer.send();
        await survey.save();
        req.user.credits -= 1;
        const user = await req.user.save();

        res.send(user);
     catch (err) 
        res.status(422).send(err);
    
);
;

【问题讨论】:

它记录 surveyId: ':surverId' 因为您正在打印 req.params。您必须打印 id 或 req.params.surveyId 才能获得您期望的结果 即使我打印 id,它仍然显示 ':surveyId' ,我记录了 req 并且它仍然显示参数 surveyId: ':surveyId'... :( @llads 检查我的答案。我已经发布它来调试你的问题。它可以为您提供一些解决问题的线索。而且我在您发布的代码中没有看到问题。使用反应无关紧要。你可以通过浏览器触发http请求来测试你的路由 【参考方案1】:

在下面发布调试问题的详细信息

注意:如果您使用的是 Windows 操作系统,请使用命令提示符进行节点项目开发。我见过有人使用 git bash 进行节点项目开发,这会导致不必要的问题

以下是调试步骤

1.新建目录forexample test并使用npm init初始化

2.安装快递npm install --save express

3.创建一个新文件for example index.js并使用以下代码

test/index.js

var express= require("express");
var app = express();

app.get("/api/surveys/:surveyId",(req,res,next)=>
    console.log(req.params.surveyId);
    res.send('Hello World');
);

var server= app.listen(3000,()=>
    console.log("port started at ",server.address().port);
)

4.启动程序node index.js

5.从浏览器http://localhost:3000/api/surveys/llads触发http请求。值llads可以使用路径中的路径参数surveyId访问

6.如果您可以在节点控制台中看到以下输出,则程序正在正常运行。这必须按照这里的描述工作。

如果上述步骤产生预期的输出,那么我在您的路由代码中看不到任何问题。

让我知道您的反馈。

【讨论】:

感谢@divine,我已按照您的调试步骤操作并得到了预期的结果。但是,我在实际项目中的 index.js 文件中没有路由。我将在我的编辑部分添加我的 index.js 文件和调查模型路由 js。如果你能看一下,看看你是否有任何线索,那就太好了。 @llads 在 index.js 中有路由逻辑可能无法解决您的问题。你的完整代码在哪里?我去看看 您确定您的请求到达了路线 /api/surveys/:surveyId 吗?在此方法中添加额外的 console.log 以确认是否触发了此特定路由。你能通过浏览器触发这条路由并测试吗? 啊,我知道了,我测试了 /api/surveys/:surveyId,它确实抓住了 id。我想我的前端路由有问题。非常感谢你为我解决了这个问题。我还有一个问题,但你不回答也没关系,因为它与此关系不大。我想将后端/api/surveys/:surveyId 中的数据导入到前端视图/surveys/:surveyId,我应该在哪里查看可能出错的地方? 而不是发送 res.send('Hello World');你可以像这样发送 json 对象 res.send("data":dataJSONObject); . Express 会自动识别它的 JSON 对象,并在响应中将 contenttype 设置为 application/json。您可以在 axios .then 回调中获取此对象。通过这种方式,您可以将数据从您的服务器路由发送到前端代码

以上是关于如何从服务器端 express/mongo/mongoose 中的 URL,客户端的 axios/react/redux 中获取参数 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C# 从服务器端删除 facebook cookie?

如何从 couchdb 运行服务器端代码?

如何从服务器端模拟复杂的 REST 调用?

如果你有 apollo react 钩子从后端获取数据,你如何使用 nextjs 进行服务器端渲染?

如何从服务器端对象调用 javascript 对象的属性/方法

如何随时从服务器端访问phonegap应用程序