简体   繁体   English

无法在Heroku上的Node + Express网站中的index.js中创建新路由

[英]Can't create new route in index.js in node+express website on heroku

I had the following index.js file: 我有以下index.js文件:

const express = require('express');
const path = require('path');
const generatePassword = require('password-generator');
const fetch = require('node-fetch');
const FetchTweets = require('fetch-tweets');
const request = require('request');

const TW_URL = "http://1.1/search/tweets.json"  // Twitter search URL
const SEN_URL =  "http://www.sentiment140.com/api/bulkClassifyJson" // URL of sentiment analysis

var TW_KEYS = {
  consumer_key: process.env.TW_KEY,
  consumer_secret: process.env.TW_SECRET
}

const app = express();
const fetchTweets = new FetchTweets(TW_KEYS);

// Serve static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));

// Put all API endpoints under '/api'
app.get('/api/passwords', (req, res) => {
  const count = 5;

  // Generate some passwords
  const passwords = Array.from(Array(count).keys()).map(i =>
    generatePassword(12, false)
  )

  // Return them as json
  res.json(passwords);

  console.log(`Sent ${count} passwords`);
});

// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname+'/client/build/index.html'));
});

const port = process.env.PORT || 5000;
app.listen(port);

console.log(`Password generator listening on ${port}`);

Along with my react App.js: 连同我的React App.js:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  // Initialize state
  state = { passwords: [] }

  // Fetch passwords after first mount
  componentDidMount() {
    this.getPasswords();
  }

  getPasswords = () => {
    // Get the passwords and store them in state
    fetch('/api/passwords')
      .then(res => res.json())
      .then(passwords => this.setState({ passwords }));
  }

  render() {
    const { passwords } = this.state;

    return (
      <div className="App">
        {/* Render the passwords if we have them */}
        {passwords.length ? (
          <div>
            <h1>5 Passwords.</h1>
            <ul className="passwords">
              {/*
                Generally it's bad to use "index" as a key.
                It's ok for this example because there will always
                be the same number of passwords, and they never
                change positions in the array.
              */}
              {passwords.map((password, index) =>
                <li key={index}>
                  {password}
                </li>
              )}
            </ul>
            <button
              className="more"
              onClick={this.getPasswords}>
              Get More
            </button>
          </div>
        ) : (
          // Render a helpful message otherwise
          <div>
            <h1>No passwords :(</h1>
            <button
              className="more"
              onClick={this.getPasswords}>
              Try Again?
            </button>
          </div>
        )}
      </div>
    );
  }
}

export default App;

It worked beautifully. 它工作得很漂亮。 Now, I want to add a new route so I've changed index.js to: 现在,我想添加一条新路由,因此将index.js更改为:

const express = require('express');
const path = require('path');
const generatePassword = require('password-generator');
const fetch = require('node-fetch');
const FetchTweets = require('fetch-tweets');
const request = require('request');

const TW_URL = "http://1.1/search/tweets.json"  // Twitter search URL
const SEN_URL =  "http://www.sentiment140.com/api/bulkClassifyJson" // URL of sentiment analysis

var TW_KEYS = {
  consumer_key: process.env.TW_KEY,
  consumer_secret: process.env.TW_SECRET
}

const app = express();
const fetchTweets = new FetchTweets(TW_KEYS);

// Serve static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));

app.get('/api/sentiment', async (req, res) => {
  console.log("matched /api/sentiment pattern")
  const options = {
    q : req.query.q,
    lang : "en",
    count : 100,
  }
  try{
    fetchTweets.byTopic(options, async function(results){
      const tweets = {"data": results.map(function(tweet){
        return {"text": tweet.body, "query": options.q}
      })}
      var body = JSON.stringify(tweets)

      // get sentiments
      const sentiments = await fetch(SEN_URL, {method: "POST", body: body})
      const json = await sentiments.json()
      const data = json.data

      //console.log(data)

      // calculate percentages
      const response = {positive: undefined, neutral: undefined, negative: undefined}
      var numPos = 0
      var numNeu = 0
      var numNeg = 0
      //console.log(response)
      data.forEach(function(tweet){
        switch(tweet.polarity){
          case 4:
            numPos += 1
            break
          case 2:
            numNeu += 1
            break
          case 0:
            numNeg += 1
            break
        }
      })
      const tot = numPos + numNeu + numNeg
      response.positive = numPos/tot
      response.neutral = numNeu/tot
      response.negative = numNeg/tot
      // send response
      res.send(response)
    })
  }catch (error){
    console.log(error)
  }
})

// Put all API endpoints under '/api'
app.get('/api/passwords', (req, res) => {
  const count = 5;

  // Generate some passwords
  const passwords = Array.from(Array(count).keys()).map(i =>
    generatePassword(12, false)
  )

  // Return them as json
  res.json(passwords);

  console.log(`Sent ${count} passwords`);
});

// The "catchall" handler: for any request that doesn't
// match one above, send back React's index.html file.
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname+'/client/build/index.html'));
});

const port = process.env.PORT || 5000;
app.listen(port);

console.log(`Password generator listening on ${port}`);

Note the new route /api/sentiments . 注意新的路由/api/sentiments I've also made a call to this new URL path in my App.js: 我还在App.js中调用了这个新的URL路径:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  // Initialize state
  state = { passwords: [] }

  // Fetch passwords after first mount
  componentDidMount() {
    this.getPasswords();
    this.getSentiments();
  }

  getSentiments = () => {
    fetch("/api/sentiment?q=hello")
      .then(res => console.log(res))

  }

The getSentiments function is what does the api call to the new route. getSentiments函数是api对新路由的调用。 But this doesn't work. 但这是行不通的。 Here's the browser console message: 这是浏览器控制台消息:

GET https://glacial-refuge-37109.herokuapp.com/api/sentiment?q=hello 503 (Service Unavailable)
i.getSentiments @ App.js:15
value @ App.js:11
commitLifeCycles @ react-dom.production.min.js:159
C @ react-dom.production.min.js:185
w @ react-dom.production.min.js:182
g @ react-dom.production.min.js:181
v @ react-dom.production.min.js:181
h @ react-dom.production.min.js:180
s @ react-dom.production.min.js:179
t @ react-dom.production.min.js:190
updateContainer @ react-dom.production.min.js:191
nn.render @ react-dom.production.min.js:228
(anonymous) @ react-dom.production.min.js:242
unbatchedUpdates @ react-dom.production.min.js:188
ln @ react-dom.production.min.js:242
render @ react-dom.production.min.js:244
(anonymous) @ index.js:7
t @ bootstrap 8940ebd453621d06336e:19
(anonymous) @ main.1f99a125.js:526
t @ bootstrap 8940ebd453621d06336e:19
(anonymous) @ bootstrap 8940ebd453621d06336e:62
(anonymous) @ bootstrap 8940ebd453621d06336e:62
App.js:16 Response {type: "basic", url: "https://glacial-refuge-37109.herokuapp.com/api/sentiment?q=hello", redirected: false, status: 503, ok: false, …}

Looks like I'm getting 503, service unavailable. 看来我收到503,服务不可用。 Why? 为什么? How can I make this work? 我该如何进行这项工作? Btw, this works fine locally. 顺便说一句,这在本地工作正常。

Add a res.send within your catch block 添加res.send您的catch块

app.get('/api/sentiment', async (req, res) => {
  console.log("matched /api/sentiment pattern")
  const options = {
    q : req.query.q,
    lang : "en",
    count : 100,
  }
  try{
    fetchTweets.byTopic(options, async function(results){
      const tweets = {"data": results.map(function(tweet){
        return {"text": tweet.body, "query": options.q}
      })}
      var body = JSON.stringify(tweets)

      // get sentiments
      const sentiments = await fetch(SEN_URL, {method: "POST", body: body})
      const json = await sentiments.json()
      const data = json.data

      //console.log(data)

      // calculate percentages
      const response = {positive: undefined, neutral: undefined, negative: undefined}
      var numPos = 0
      var numNeu = 0
      var numNeg = 0
      //console.log(response)
      data.forEach(function(tweet){
        switch(tweet.polarity){
          case 4:
            numPos += 1
            break
          case 2:
            numNeu += 1
            break
          case 0:
            numNeg += 1
            break
        }
      })
      const tot = numPos + numNeu + numNeg
      response.positive = numPos/tot
      response.neutral = numNeu/tot
      response.negative = numNeg/tot
      // send response
      res.send(response)
    })
  }catch (error){
    console.log(error)
    res.send(error)
  }
})

Your function is failing and because you don't send a response, hangs forever 您的函数失败,并且由于您未发送响应,因此会永远挂起

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM