使用Express后PUT路由后不执行代码

时间:2017-10-08 21:46:52

标签: javascript node.js express

我在!overlay聊天时听tmijs library的聊天事件,我想执行一些代码。获得该消息后我想要实现的目标是:

  • 获取用户
  • 检查用户是否有足够的货币
  • 从用户中扣除货币
  • 触发套接字事件到我的反应应用

直到最后一个要点,一切似乎都有效。在我的终端中,显示我的用户获得了货币(在我的代码中称为'kluiten'),但是在它之后的所有代码都没有被执行。

require('dotenv').config();
const PORT = process.env.PORT || 9000;

class TwitchAPI {
  constructor({io}) {
    this.io = io;
    this.client = new tmi.client(options);

    this.client.connect();

    this.handleOverlayRequest = this.handleOverlayRequest.bind(this);
    this.handleChatMessage = this.handleChatMessage.bind(this);

    this.client.on('chat', this.handleChatMessage);
  }

  handleChatMessage (channel, userstate, message) {
   if(message === '!overlay') this.handleOverlayRequest(channel, userstate);
  }

  async handleOverlayRequest (channel, userstate) {
    const requiredKluiten = 5;
    const rawFoundUser = await fetch(`http://localhost:${PORT}/api/users/${userstate.username}`);
    const foundUser = await rawFoundUser.json();

    if(foundUser.instakluiten >= requiredKluiten) {
      this.client.action(channel, `${userstate[`display-name`]}, you've got enough instakluiten for this.`);

      const method = `PUT`;
      const payload = { 'requiredKluiten': requiredKluiten };
      const body = JSON.stringify(payload);
      const headers = { 'Content-Type': `application/json; charset=utf-8` };

      const result = await fetch(`http://localhost:${PORT}/api/users/${userstate.username}/decrementKluiten`, { method, body, headers });
      console.log(result);
    }
  }
}

module.exports = TwitchAPI;

然后我有一个Express路由器:

const express = require('express');
const userController = require('../controllers/userController');

const router = express.Router();

router.route('/users/:username/decrementKluiten').put(userController.decrementKluiten);
router.route('/users/:username').get(userController.getUser);
router.route('/overview').get(userController.getOverview);

module.exports = router;

确保扣除货币。我现在坚持的是,在发生这一切之后,我在获取后不再执行任何代码。我发现虽然我可以通过解决我的路线中的承诺来执行代码,但这感觉非常脏并且弄乱了我的分割文件:

router.route('/users/:username/decrementKluiten').put((req, res) => {
 userController.decrementKluiten(req, res).then(x => {
  console.log(x);
 });
});

有没有办法等待我的PUT发生并仍然执行代码后呢?

修改

userController.js

const {findChattersPerRole, getUserByUsername, decrementKluiten} = require('../actions');
const find = require(`lodash/find`);
const fetch = require(`isomorphic-fetch`);
const parseJSON = response => response.json();

module.exports = {
  getUser: (req, res) => {
    const username = req.params.username;
    findChattersPerRole()
      .then(chattersPerRole => {
        const wantedUser = find(chattersPerRole, { username });
        getUserByUsername(wantedUser.username)
          .then(foundUser => {
            if (foundUser) {
              res.send(foundUser);
            } else {
              res.send(`No user has been found`);
            }
          });
      });
  },
  getOverview: (req, res) => {
    fetch(`https://tmi.twitch.tv/group/user/instak/chatters`)
    .then(parseJSON)
    .then(r => {
      return res.json(r);
    }).catch(err => {
      console.log(err);
    });
  },
  decrementKluiten: (req, res) => {
    decrementKluiten(req.params.username, req.body.requiredKluiten);
  }
}

actions.js

因为这包含大量代码,我尝试仅包含此帖子的相关部分,数据库调用是使用Sequelize.js 完成的)

const decrementKluiten = (username, requiredKluiten) => {
  return global.db.Viewer.findOne({
    where: { username }
  }).then(user => {
    return user.decrement({ instakluiten: requiredKluiten });
  });
};

module.exports = {
  decrementKluiten
};

1 个答案:

答案 0 :(得分:1)

问题可能是您没有回复/users/:username/decrementKluiten路由中的HTTP请求。要解决此问题,请将decrementKluiten - 文件中的导出userController.js方法更改为:

decrementKluiten: (req, res) => {
  decrementKluiten(req.params.username, req.body.requiredKluiten)
    .then(() => res.sendStatus(200))
    .catch(() => res.sendStatus(500));
}

一些不相关的指针使你的代码更具可读性,因为你已经在代码的某些部分使用了async函数,但在其他部分你直接与Promises接口。

userController.js的导出部分可以使用async函数:

module.exports = {
  getUser: async (req, res) => {
    try {
      const username = req.params.username;
      let chattersPerRole = await findChattersPerRole();
      let wantedUser = find(chattersPerRole, { username });
      let foundUser = await getUserByUsername(watnerUser.username);
      if (foundUser) {
        res.status(200).send(foundUser);
      } else {
        res.status(404).send('No user has been found');
      }
    } catch (e) {
      res.sendStatus(500);
    }
  },
  getOverview: async (req, res) => {
    try {
      let r = (await fetch('https://tmi.twitch.tv/group/user/instak/chatters')).json();
      res.json(r);
    } catch (e) {
      res.sendStatus(500);
    }
  },
  decrementKluiten: async (req, res) => {
    try {
      await decrementKluiten(req.params.username, req.body.requiredKluiten);
      res.sendStatus(200);
    } catch (e) {
      res.sendStatus(500);
    }
  }
}

我还添加了错误处理,以防出现问题,服务器以500 Internal Server Error状态代码响应。

根据TwitchAPI课程中的这些行来判断:

const rawFoundUser = await fetch(`http://localhost:${PORT}/api/users/${userstate.username}`);
const foundUser = await rawFoundUser.json();

我假设您已尝试const foundUser = await fetch('...').json()。这会导致错误,但如果将await表达式括在括号中,则可以在同一行调用重新调整的值的方法和属性,如下所示:

const foundUser = await (await fetch('...')).json()`

如果它的方法没有返回Promise(即同步),或者你想访问一个属性,你可以这样做:

const something = (await doSomethingAsync()).someMethod()
const somethingElse = (await doSomethingAsync()).property

我还注意到你在没有进行任何模板插值的情况下对大多数字符串使用模板文字(反引号,`),这可以简单地替换为'(单引号)或{{1 (双引号)。