VueJS Ошибка в переменной обработчика v-on this. не определено - PullRequest
0 голосов
/ 05 апреля 2019

Работа в VueJS с API-интерфейсом MongoDB / Express, попытка добавить новую запись в модель Bookmarks с одним полем url, но с ошибкой, которую я пытаюсь передать в поле URL-адреса, - undefined.Я использовал этот шаблон для вызовов API раньше без проблем, поэтому я не уверен, что происходит в этот раз.

с консоли:

Error in v-on handler (Promise/async): "Error: Request failed with             status code 500"

на вкладке сети:

{"errors":{"message":"Cannot read property 'url' of undefined","error":{}}}

вот компонент:

<template>
  <div class="bookmarks">
    <h1>Add a Bookmark</h1>
    <div class="form">
      <div>
        <input type="text" placeholder="Enter a URL" v-model="url">
      </div>
      <div>
        <button class="app_post_btn" @click="addBookmark">Save</button>
      </div>
    </div>
  </div>
</template>

<script>
import BookmarksService from '@/services/BookmarksService'
export default {
  name: 'NewBookmark',

  data () {
    return {
      url: ''
    }
  },
  methods: {
    async addBookmark () {
      await BookmarksService.addBookmark({
        url: this.url
      })
      this.$router.push({ name: 'Bookmarks' })
    }
  }
}
</script>

<style type='text/css'>
.form input,
.form textarea {
  width: 500px;
  padding: 10px;
  border: 1px solid #e0dede;
  outline: none;
  font-size: 12px;
}
.form div {
  margin: 20px;
}

.app_post_btn {
  background: #4d7ef7;
  color: #fff;
  padding: 10px 80px;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: bold;
  width: 520px;
  border: none;
  cursor: pointer;
}
</style>

API-вызов к серверу происходит через папку services, поэтому в BookmarksService.js:

import Api from '@/services/Api'

export default {
  fetchBookmarks () {
    return Api().get('bookmarks')
  },

  addBookmark (params) {
    return Api().post('bookmarks', params)
  }
...

Api.js:

import axios from 'axios'
const token = localStorage.getItem('token')

export default () => {
  return axios.create({
    baseURL: 'http://localhost:8000/api',
    headers: {
      'Content-Type': 'application/json',
      token: token,

    }
  })
}

В ответ на комментарии ниже приведена информация о запросе:

Request URL: http://localhost:8000/api/bookmarks
Request Method: POST
Status Code: 500 Internal Server Error
Remote Address: [::1]:8000
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 75
Content-Type: application/json; charset=utf-8
Date: Fri, 05 Apr 2019 16:47:01 GMT
ETag: W/"4b-DnvHolHvXjMbxmLeqrleWSWRA0Q"
X-Powered-By: Express
Provisional headers are shown
Accept: application/json, text/plain, */*
authorization: Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJvbmVAZ21haWwuY29tIiwiaWQiOiI1YzlmOTcxY2E3YzIyNTc1ZTFjYzkwMDUiLCJleHAiOjE1NTk2NjY3ODcsImlhdCI6MTU1NDQ4Mjc4N30.zlrqFfj2r7K_1iAVm7m2w_kUeqFH3ZvsDJkIK7UOUu8
Content-Type: application/json
Origin: http://localhost:8080
Referer: http://localhost:8080/
token: Token undefined
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
{url: "http://axios.com"}
url: "http://axios.com"

на стороне сервера:

здесь - почтовый маршрут:

const mongoose = require('mongoose');
const passport = require('passport');
const router = require('express').Router();
const auth = require('../auth');
const Bookmarks = mongoose.model('Bookmarks');

//POST new user route (optional, everyone has access)
router.post('/', auth.required, (req, res, next) => {
  const userId = req.user.id;
  const bookmark = req.body.bookmark;

  if(!bookmark.url) {
    return res.status(422).json({
      errors: {
        url: 'is required',
      },
    });
  }

  bookmark.userId = userId;
  const finalBookmark = new Bookmarks(bookmark);

  return finalBookmark.save()
    .then(() => res.json({ bookmark: finalBookmark }));
});

...

файл app.js из экспресс-приложения:

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const session = require('express-session');
const cors = require('cors');
const mongoose = require('mongoose');
const errorHandler = require('errorhandler');

//Configure mongoose's promise to global promise
mongoose.promise = global.Promise;

//Configure isProduction variable
const isProduction = process.env.NODE_ENV === 'production';

//Initiate our app
const app = express();

//Configure our app
app.use(cors());
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({ secret: 'bookmarks-darius', cookie: { maxAge: 60000 }, resave: false, saveUninitialized: false }));

if(!isProduction) {
  app.use(errorHandler());
}

//Configure Mongoose
mongoose.connect('mongodb://localhost/bookmarks', { useNewUrlParser: true });
mongoose.set('debug', true);

//Models & routes
require('./models/Users');
require('./models/Bookmarks');
require('./config/passport');
app.use(require('./routes'));

// express doesn't consider not found 404 as an error so we need to handle 404 explicitly handle 404 error
app.use(function(req, res, next) {
  if (err) {
    next(err);
  } else { // no error thrown by another route, so we must not have found a route, therefore return a 404
    let err = new Error('Not Found');
    err.status = 404;
    next(err);
  }
});

//Error handlers & middlewares
if(!isProduction) {
  app.use(function (err, req, res, next) {
    res.status(err.status || 500);

    res.json({
      errors: {
        message: err.message,
        error: err,
      },
    });
  });
}

app.use(function (err, req, res, next) {
  res.status(err.status || 500);

  res.json({
    errors: {
      message: err.message,
      error: {},
    },
  });
});

app.listen(8000, () => console.log('Server running on http://localhost:8000/'));

Ответы [ 2 ]

0 голосов
/ 07 апреля 2019

Основная часть запроса, поступающего с вашего веб-интерфейса, не соответствует вашим ожиданиям.
Основная проблема заключается в том, что в функции addBookmark в компоненте vue.js вы передаете объект, который имеет единственное свойство 'url', тогда как в вашем бэкэнд-сервисе вы ожидаете объект 'bookmark', который содержит свойство'URL'.Вы также можете увидеть это в теле запроса: {url: "http://axios.com"} Изменение кода вашего компонента на

async addBookmark () {
  await BookmarksService.addBookmark({
    bookmark: {
               url: this.url
           }
  })
  this.$router.push({ name: 'Bookmarks' })
}

должно работать.Вы должны получить что-то вроде этого { bookmark: {url: "http://axios.com"} }.В любом случае проверяйте любое свойство, полученное из тела запроса, как сказал Фил, - это всегда хорошая практика, которой вы должны следовать.

0 голосов
/ 07 апреля 2019

Смотрите ниже фрагмент.Всегда проверяйте любое свойство, которое исходит от тела.

router.post('/', auth.required, (req, res, next) => {
  const userId = req.user.id;
  const bookmark = req.body.bookmark; <---- bookmark is undefined

  if(!bookmark.url) { <---- undefined.url -> Error.
    return res.status(422).json({
      errors: {
        url: 'is required',
      },
    });
  }

  // ...
});
...