Javascript Can';t在节点+;的index.js中创建新路由;heroku速递网站

Javascript Can';t在节点+;的index.js中创建新路由;heroku速递网站,javascript,node.js,reactjs,express,Javascript,Node.js,Reactjs,Express,我有以下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('reque

我有以下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}`);
连同我的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;
请注意新路线
/api/continues
。我还在我的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))

  }
函数是api对新路由的调用。但这不起作用。以下是浏览器控制台消息:

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, …}

看起来我得到503,服务不可用。为什么?我怎样才能做到这一点?顺便说一句,这在本地运行良好。

在catch块中添加一个
res.send

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)
  }
})

您的功能正在失败,因为您没有发送响应,所以将永远挂起

是否只是在浏览器中失败?我猜你遇到了CORS问题。尝试通过PostMani向端点发出请求。同样,通过postman也会失败。当我尝试获取时,它只是永久加载,然后返回一些HTML页面,而不是我所期望的json页面。您是否可以使用它?
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)
  }
})