Как исправить 'TypeError: Не удалось получить'? - PullRequest
0 голосов
/ 04 июля 2019

Я получаю сообщение об ошибке TypeError: Failed to fetch, когда пытаюсь отправить почтовый запрос, используя fetch на внешнем интерфейсе и экспресс-маршрут на серверном конце.

Я могу успешно создать нового пользователя в БД, но при попытке получить эти новые пользовательские данные с помощью обещания выборки именно тогда выдается ошибка.

app.js

function createNewUser() {
  let formUsername = document.getElementById('signup-username').value;
  let formEmail = document.getElementById('signup-email').value;
  let formPassword = document.getElementById('signup-password').value;
  let url = "/users";
  let newUserData = {
    username: formUsername,
    email: formEmail,
    password: formPassword
  }

  fetch(url, {
    method: 'POST',
    cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
    credentials: 'same-origin', // include, *same-origin, omit
    headers: {
        'Content-Type': 'application/json'
    },
    redirect: 'follow', // manual, *follow, error
    referrer: 'no-referrer',
    body: JSON.stringify(newUserData),
  }).then(res => res.json())
  .then(response => console.log('Success: ', JSON.stringify(response)))
  .catch(error => console.error('Error: ', error));
}

users.js

router.post('/users', function(req, res) {
   User.create(req.body)
   .then(function(user) {
      res.json({
         user: user
      })
   }
});

server.js

const express = require('express');
const app = express();
const fs = require('fs');
const path = require('path');
const bodyParser = require('body-parser');
const bcrypt = require('bcryptjs');
const auth = require('./auth');
const router = require('./routes/routes.js');

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(router);

app.use('/', express.static(path.join(__dirname, 'public')));

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE" // what matters here is that OPTIONS is present
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization", "Access-Control-Allow-Origin");
  next();
});

app.listen(3000, function(){
  console.log("Listening on port 3000");
});

Мне нужно вернуть этот пользовательский объект для доступа к его данным.

Edit: Итак, я выяснил, что проблема связана с тем, как запрос передается на внешний интерфейс. Если я создаю следующую функцию и затем вызываю ее при загрузке app.js, то все работает:

function createNewUserTest() {
  let formUsername = 'dd';
  let formEmail = 'd@d.com';
  let formPassword = 'secrete';
  let url = "/api/users";
  let newUserData = {
    username: formUsername,
    email: formEmail,
    password: formPassword
  }
  fetch(url, {
    method: 'POST',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(newUserData),
  })
  .then(res => res.json())
  .then(response => console.log('Success: ', response))
  .catch(error => console.error('Error: ', error));
}

createNewUserTest();

Но, если я попытаюсь вызвать эту функцию через onsubmit в форме или onclick на кнопке в html, или если я использую прослушиватель событий (см. Ниже, который находится в app.js), тогда я получаю TypeError: Failed to fetch ошибку:

let signupSubmitButton = document.getElementById('signup-submit');
signupSubmitButton.addEventListener('click', createNewUserTest);

Это еще более озадачивает меня. Мне нужно использовать Vanilla JS, и мне нужно создать пользователя с помощью отправки формы, но я не уверен, что мне нужно настроить здесь.

Решение Сорванный event.preventDefault() снова. Это было все, что мне было нужно.

let signupForm = document.getElementById('signup-form');
signupForm.addEventListener('submit', function(event) {
  event.preventDefault();
  let formUsername = document.getElementById('signup-username').value;
  let formEmail = document.getElementById('signup-email').value;
  let formPassword = document.getElementById('signup-password').value;
  let url = "/api/users";
  let newUserData = {
    username: formUsername,
    email: formEmail,
    password: formPassword
  }
  fetch(url, {
    method: 'POST',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(newUserData),
  })
  .then(res => res.json())
  .then(response => console.log('Success: ', response))
  .catch(error => console.error('Error: ', error));
});

Ответы [ 2 ]

0 голосов
/ 05 июля 2019

Проблема заключалась в том, что страница перезагружалась, что не давало мне вернуть данные вовремя. Решением было просто добавить event.preventDefault() внутри слушателя.

app.js

let signupForm = document.getElementById('signup-form');
signupForm.addEventListener('submit', function(event) {
  event.preventDefault();
  let formUsername = document.getElementById('signup-username').value;
  let formEmail = document.getElementById('signup-email').value;
  let formPassword = document.getElementById('signup-password').value;
  let url = "/api/users";
  let newUserData = {
    username: formUsername,
    email: formEmail,
    password: formPassword
  }
  fetch(url, {
    method: 'POST',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(newUserData),
  })
  .then(res => res.json())
  .then(response => console.log('Success: ', response))
  .catch(error => console.error('Error: ', error));
});
0 голосов
/ 04 июля 2019

Когда речь идет о проблемах с CORS, это очень часто, потому что сервер не знает, как с этим справиться. По сути, каждый раз, когда вы включаете заголовок, такой как access-control-origin, в ваш запрос он также инициирует предварительный запрос OPTIONS, и если ваш сервер не ожидает, что он выдаст ошибку, потому что он ожидал только запросы POST.

Другими словами - попробуйте снова без части "Access-Control-Origin": "*" и посмотрите, работает ли она, или просто попробуйте установить исправление на сервере с помощью чего-то вроде этого:

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE" // what matters here is that OPTIONS is present
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  next();
});
...