如何修复“TypeError:无法获取"?

2022-01-20 00:00:00 node.js express fetch javascript

当我尝试在前端使用 fetch 并在后端使用快速路由发送发布请求时,我收到 TypeError: Failed to fetch 错误-结束.

I'm getting a TypeError: Failed to fetch error when I attempt to send a post request using fetch on the front-end and an express route on the back-end.

我能够在数据库中成功创建新用户,但是当尝试通过 fetch promise 获取新用户数据时,就会抛出错误.

I'm able to successfully create the new user in the db, but when attempting to obtain that new user data through the fetch promise, that's when the error is being thrown.

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

我需要取回该用户对象才能访问其数据.

I need to get that user object back in order to access its data.

所以,我发现问题与如何在前端提交请求有关.如果我创建以下函数,然后在加载 app.js 时调用它,那么一切正常:

So, I've figured out that the issue has to do with how the request is submitted on the front-end. If I create the following function and then call it when app.js is loaded, then everything works:

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 或 html 中按钮上的 onclick 调用此函数,或者如果我使用事件侦听器(请参阅下面,在 app.js 中),然后我得到 TypeError: Failed to fetch 错误:

But, if I try to call this function either through onsubmit in the form or onclick on the button in the html, or if I use an event listener (see below, which is in app.js), then I get the TypeError: Failed to fetch error:

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

这对我来说更加莫名其妙.我需要使用Vanilla JS,我需要通过表单提交来创建用户,但不确定我需要在这里调整什么.

This is even more baffling to me. I'm required to use Vanilla JS and I need to create the user through a form submission, but not sure what I need to adjust here.

解决方案再次被 event.preventDefault() 挫败.这就是我所需要的.

Solution Foiled by the event.preventDefault() again. This was all I needed.

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

推荐答案

问题是页面正在重新加载,这使我无法及时获取数据.解决方案是在侦听器中简单地添加 event.preventDefault().

The issue was that the page was reloading, which kept me from getting the data back in time. The solution was to simply add event.preventDefault() inside the listener.

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

相关文章