无法使Nuxt.js,Express和第三方API一起使用

问题描述 投票:0回答:1

我已经尝试了数周时间,以使Nuxt.js + Express(使用create-nuxt-app)与第三方API一起使用。无论我尝试什么,都没有,绝对没有任何效果。我的服务器端没有控制台语句被触发,只有前端语句被触发。另外,我最近开始获取Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client,并且没有在代码中的任何位置设置标头。

我要做的就是获取用户输入,将其传递到后端以避免CORS问题,从第三方API取回数据,然后显示它。这很简单。它一直在互联网上发生,所以为什么我不能使它工作?

下面是上述过程中涉及的所有文件。

pages / index.vue:

<template>
  <div class="container">
    <img src="@/assets/images/OscarPark.jpg" alt="Oscar in the park" title="I love the park!" />
    <br />
    <form>
      <label for="title">Book Title:</label>
      <input v-model="titleFromUser" type="text" name="title" class="title" />
      <button @click.prevent="submit" class="submit">Find a Book!</button>
    </form>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  components: {},
  data() {
    return {
      titleFromUser: '',
    };
  },
  computed: mapState(['newTitles']),
  methods: {
    submit() {
      this.$store.dispatch('FETCH_BOOK_TITLES', this.titleFromUser);
      this.titleFromUser = '';
    },
  },
};
</script>

<style lang="scss">
.container {
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;

  img {
    transform: rotate(90deg); // this fixes a glitch that causes image to rotate needlessly
    padding-top: $underHeaderGap; // these 2 padding lines help to fix the placement of the image caused by the needless rotation
    padding-left: $underHeaderGap * 5;
    margin-bottom: $underHeaderGap * 5;
    height: $imgHeight;
  }
}
</style>

store / index.js:

import consola from 'consola';

export const state = () => ({
  newTitles: [],
});

export const mutations = {
  SET_NEW_TITLES(state, newTitles) {
    state.newTitles = newTitles;
  },
};

export const actions = {
  async FETCH_BOOK_TITLES({ commit }, titleFromUser) {
    try {
      consola.ready({
        message: `'FETCH_BOOK_TITLES': titleFromUser: ${titleFromUser}`,
        badge: true,
      });
      const { data } = await this.$axios.$post('/title', { titleFromUser });
      consola.ready({
        message: `data returned from api: ${data}`,
        badge: true,
      });
      commit('SET_NEW_TITLES', data);
    } catch (error) {
      consola.error({
        message: `FETCH_BOOK_TITLES: Something went wrong: ${error}`,
        badge: true,
      });
      throw new Error(error);
    }
  },
};

server / index.js:

const express = require('express');
const cors = require('cors');
const consola = require('consola');
const axios = require('axios');
const { Nuxt, Builder } = require('nuxt');
const app = express();
const jsonParser = express.json();

const titleRouter = require('../api/title/index');

// Import and Set Nuxt.js options
const config = require('../nuxt.config.js');
config.dev = process.env.NODE_ENV !== 'production';

async function start() {
  // Init Nuxt.js
  const nuxt = new Nuxt(config);

  const { host, port } = nuxt.options.server;

  // Give app ability to parse json
  app.use(jsonParser);

  // Give app ability to get past CORS issues
  app.use(cors());

  // Give nuxt middleware to express
  app.use(nuxt.render);

  // Build only in dev mode
  if (config.dev) {
    const builder = new Builder(nuxt);
    await builder.build();
  } else {
    await nuxt.ready();
  }

  app.use('/title', titleRouter);

  app.get('/title', (req, res) => {
    consola.ready({
      message: `res.json in title endpoint-server: ${res.json()}`,
      badge: true,
    });

    consola.ready({
      message: `req.json in title endpoint-server: ${req.json()}`,
      badge: true,
    });

    const recommendationsURL = `https://tastedive.com/api/similar?q=and+then+there+were+none&type=books&info=1&k=${process.env.TASTE_DIVE_API_KEY}`;

    axios
      .get(recommendationsURL, (req, res) => {
        consola.ready({
          message: `from server/index.js: ${res.json()}`,
          badge: true,
        });
      })
      .catch((error) => {
        consola.error({
          message: `error from axios server ${error} `,
          badge: true,
        });
      });
  });

  // Listen to the server
  app.listen(port, host, () => {
    consola.ready({
      message: `Server listening on http://${host}:${port}`,
      badge: true,
    });
  });
}

start();

api / title / index.js:

const consola = require('consola');
const express = require('express');
const app = express();
const titleRouter = express.Router();

titleRouter.use((req, res, next) => {
  Object.setPrototypeOf(req, app.request);
  Object.setPrototypeOf(res, app.response);
  req.res = res;
  res.req = req;
  next();
});

titleRouter.get('/title', (req, res) => {
  res
    .json()
    .then((data) => {
      consola.ready({
        message: `~api/title get title is ${data}`,
        badge: true,
      });
    })
    .catch((error) => {
      consola.error({
        message: `~api/title get Something went wrong: ${error}`,
        badge: true,
      });
      throw new Error(error);
    });
});

titleRouter.post('/title', (req, res) => {
  res
    .json()
    .then((data) => {
      consola.ready({
        message: `~api/title post title is ${data}`,
        badge: true,
      });
    })
    .catch((error) => {
      consola.error({
        message: `~api/title post Something went wrong: ${error}`,
        badge: true,
      });
      throw new Error(error);
    });
});

module.exports = titleRouter;

nuxt.config.js:

require('dotenv').config();

module.exports = {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: "Oscar's Book Recommendations",
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: process.env.npm_package_description || '',
      },
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module',
    '@nuxtjs/dotenv',
    '@nuxtjs/style-resources',
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/pwa',
    '@nuxtjs/auth',
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    https: true,
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
  },
  /*
   ** Build configuration
   */
  build: {
    watch: ['api/title'],
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {},
  },
  pageTransition: {
    name: 'fade',
    mode: 'out-in',
  },
  env: {
    TASTE_DIVE_API_KEY: process.env.TASTE_DIVE_API_KEY,
  },
  serverMiddleware: ['~api/title'],
  styleResources: {
    scss: ['~assets/styles/main.scss'],
  },
};

有人看到我不是吗?为什么数据不传递到服务器?为什么在我没有在代码中的任何位置设置标题时,告诉我在发送标题后无法设置标题?这怎么了?

我将非常感谢任何人的投入和帮助。谢谢。

rest express vue.js nuxt.js
1个回答
0
投票

好,所以碰巧我有一个server/index.js和一个带有nuxt.config.js条目的serverMiddleware。努克斯(Nuxt)的创建者之一塞巴斯蒂安·肖邦(Sebastien Chopin)看到了我关于此问题的推文,并指出我可以在server/index.js中使用serverMiddleware文件或nuxt.config.js,但不能同时使用。作为最初通过创建服务器文件来学习Express的人,我可以很容易地看到这将如何引起人们的困惑。

[最后,我决定使用Nuxt方法,并在serverMiddleware中使用了nuxt.config.js。当您设置Nuxt项目并选择从一开始就集成Express时,与传统的服务器文件相比,这是使用Express的首选方式。

© www.soinside.com 2019 - 2024. All rights reserved.