【问题标题】:Why am I getting an error of Unexpected token < in JSON at position 0为什么我在位置 0 的 JSON 中收到 Unexpected token < 的错误
【发布时间】:2020-10-01 21:12:49
【问题描述】:

我正在创建一个 MERN 应用程序,我是新手。我尝试在网上学习一些教程,但遇到了一些错误。

我正在提交这样的发布请求。如您所见,我没有指定内容类型,因为我知道如果您使用'multipart/form-data,它会自动将其附加到标题中。我在这里使用了一个反应钩子,这就是为什么我不直接使用 fetch 方法。

const formData = new FormData();
formData.append("email", formState.inputs.email.value);
formData.append("name", formState.inputs.name.value);
formData.append("password", formState.inputs.password.value);
formData.append("image", formState.inputs.image.value);
const responseData = await sendRequest(
    `${process.env.REACT_APP_BACKEND_BASE_URL}/api/users/signup`,
    "POST",
    formData
    );

同时我的注册路线是这样的,在 user-routes.js 下

router.post(
  "/signup",
  fileUpload.single("image"),
  [
    check("name").not().isEmpty(),
    check("email")
      .normalizeEmail() // Test@test.com => test@test.com
      .isEmail(),
    check("password").isLength({ min: 6 }),
  ],
  usersController.signup
);

您也可以看到,我正在使用fileUpload.single("image") 在路线中捕获它

如果您需要查看我在这里使用的钩子,那就是,但我很确定该钩子可以正常工作。它没有任何问题,所以这里是:这是一个反应钩子

export const useHttpClient = () => {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState();

  const activeHttpRequests = useRef([]);

  const sendRequest = useCallback(
    async (url, method = "GET", body = null, headers = {}) => {
      setIsLoading(true);
      const httpAbortCtrl = new AbortController();
      activeHttpRequests.current.push(httpAbortCtrl);

      try {
        const response = await fetch(url, {
          method,
          body,
          headers,
          signal: httpAbortCtrl.signal,
        });

        const responseData = await response.json();

        // console.log("Response: ", response);
        // console.log("Data: ", responseData);

        activeHttpRequests.current = activeHttpRequests.current.filter(
          (reqCtrl) => reqCtrl !== httpAbortCtrl
        );

        if (!response.ok) {
          throw new Error(responseData.message);
        }

        setIsLoading(false);
        return responseData;
      } catch (err) {
        setError(err.message);
        setIsLoading(false);
        throw err;
      }
    },
    []
  );

  const clearError = () => {
    setError(null);
  };

  useEffect(() => {
    return () => {
      // eslint-disable-next-line react-hooks/exhaustive-deps
      activeHttpRequests.current.forEach((abortCtrl) => abortCtrl.abort());
    };
  }, []);

  return { isLoading, error, sendRequest, clearError };
};

我将在此处包含我的 users.controller 的注册:

const signup = async (req, res, next) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return next(
      new HttpError("Invalid inputs passed, please check your data.", 422)
    );
  }

  const { name, email, password } = req.body;

  let existingUser;
  try {
    existingUser = await User.findOne({ email: email });
  } catch (err) {
    const error = new HttpError(
      "Signing up failed, please try again later.",
      500
    );
    return next(error);
  }

  if (existingUser) {
    const error = new HttpError(
      "User exists already, please login instead.",
      422
    );
    return next(error);
  }

  let hashedPassword;
  try {
    hashedPassword = await bcrypt.hash(password, 12);
  } catch (err) {
    const error = new HttpError(
      "Could not create user, please try again.",
      500
    );
    return next(error);
  }

  //res.json({ message: "AFTER HASHING" });

  const createdUser = new User({
    name,
    email,
    image: req.file.path,
    password: hashedPassword,
    places: [],
  });

  try {
    await createdUser.save();
  } catch (err) {
    const error = new HttpError(
      "Signing up failed, please try again later.",
      500
    );
    return next(error);
  }

  let token;
  try {
    token = jwt.sign(
      { userId: createdUser.id, email: createdUser.email },
      process.env.JWT_KEY,
      { expiresIn: "1h" }
    );
  } catch (err) {
    const error = new HttpError(
      "Signing up failed, please try again later.",
      500
    );
    return next(error);
  }

  res
    .status(201)
    .json({ userId: createdUser.id, email: createdUser.email, token: token });
};

【问题讨论】:

  • 您实际上返回的是 HTML 而不是 JSON。您必须收到 HTTP 错误,例如404.const response等待promise解析后的结果,不是JSON字符串。所以这失败了......const responseData = await response.json();
  • @Mr.Polywhirl 不,我没有返回任何 html,我从这里读到,如果您发送的内容类型为“multiform”,而您提交的数据是 json,则会遇到这种情况对象,这里是 URL:stackoverflow.com/questions/50432928/…
  • @IvanApungan 有一个非常简单的方法可以找出答案:查看浏览器开发人员工具(“网络”选项卡)中的实际 HTTP 响应正文。请注意,正如 Polywhirl 先生所说,无论您的代码是否返回 HTML,您的服务器都可以返回 HTML 格式的错误。
  • @Pointy 是的,他是正确的,似乎服务器正在返回 html 或文本类型,但我没有在注册路线中出错,我假设问题出在 multer .我正在使用 multer 上传文件
  • @Pointy 似乎我部署的服务器正在返回内部服务器错误状态代码 500,我在注册功能的每个场景中都使用了 try catch,但错误就在其中。我认为错误甚至在它进入注册块之前就发生了,也许它在我在 user-routes.js 中导入的 fileupload.js 文件中

标签: javascript reactjs multer


【解决方案1】:

您可能希望在您的 responseData 周围使用JSON.Parse()

每当我遇到这个错误时,都是因为我,

  • 解析了一个已经解析的对象
  • 字符串化
  • 使用字符串作为对象

link 更深入地介绍了该错误以及剖析问题的常用方法。

在发送数据之前尝试在你的钩子中使用 console.log() 并记录 responseData 在检索数据后的样子

【讨论】:

  • 如果response.json() 抛出语法错误,那么它这样做是因为它已经将响应正文传递给JSON.parse()
猜你喜欢
  • 2014-12-25
  • 1970-01-01
  • 2021-09-13
  • 2017-12-06
  • 2020-12-13
  • 2022-08-12
  • 2022-10-17
  • 1970-01-01
  • 2021-10-19
相关资源
最近更新 更多