【问题标题】:Promise in useEffect works, even though IntelliJ says 'Promise returned from Promise is ignored 'useEffect 中的 Promise 有效,即使 IntelliJ 说“从 Promise 返回的 Promise 被忽略”
【发布时间】:2021-07-27 21:05:14
【问题描述】:

我想知道下面的代码是如何工作的(它在下拉列表中显示正确的选项),即使 IntelliJ 中的警告说“忽略从 Promise 返回的 Promise”并建议更改代码。 初始版本代码:

import React, { useState, useEffect } from "react";
import axios from "axios";

const Cake = () => {
  const [ing, setIng] = useState([]);
  const [error, setError] = useState("");

  const getIngredients = async () => {
    // returns an array of strings
    const url = new URL("someUrl");
    const result = await axios.get(url.toString());
    return result.data;
  };

  useEffect(() => {
    new Promise((resolve, reject) => {
      getIngredients()
        .then((response) => setIng(response))
        .then((response) => resolve(response))
        .catch((error) => setError(error));
    });
  }, []);

  return (
    <div>
      <Select options={ing} />
    </div>
  );
};

export default Cake;

IntelliJ 建议在我的 Promise 中添加“then”,如下所示:

useEffect(() => {
  new Promise((resolve, reject) => {
    getIngredients()
      .then((response) => setIng(response))
      .then((response) => resolve(response))
      .catch((error) => setError(error));
  }).then((r) => console.log(r));
}, []);

【问题讨论】:

  • 将代码包装在 useEffect 挂钩中的承诺的目的是什么?我认为这里的问题是没有必要的
  • 在 Promise 构造函数中包装 getIngredients 有什么意义?你已经有一个调用getIngredients返回的promise,不需要使用promise构造函数。
  • 实际上来自new Promise的承诺被忽略了
  • 查看本文的“创建新的 Promise”部分:runnable.com/blog/…您正在链的顶部创建一个不需要的承诺 - getIngredients() 函数已经返回一个 Promise
  • @JuanMendes return getIngredients(...) 不需要。 useEffect 挂钩的有效返回值是用作 cleanup 函数的函数。

标签: javascript reactjs promise


【解决方案1】:

您根本不应该在这里创建 new Promise(正如 IntelliJ 所说,它甚至没有在任何地方使用),它也是 Promise constructor antipatternresolve 的一个承诺,来自另一个承诺的 .then() 回调.

你所需要的只是

useEffect(() => {
    getIngredients().then(setIng, setError);
}, []);

【讨论】:

  • 谢谢!关于“.then(...)”内部的部分,我还有一个问题:在这种情况下,不需要捕获错误吗?我看到在您提供的链接中提到了“.then 和 .catch 处理程序的不必要的函数包装器”,但老实说,我在理解它时遇到了问题。你能解释一下为什么你决定省略“.catch()”部分吗?
  • 我使用.then(…, …) instead of .then(…).catch(…) 处理来自getIngredients 的错误。 setIng 预计不会抛出,如果抛出,则该错误未处理(与 setError 抛出的另一个错误相同)。
  • 我认为使用catch 是首选方法,而不是第二个参数。如果第一个参数 (setIng) 发生错误,则不会调用第二个参数 (setError)。 catch 总是被调用。见jsfiddle.net/mendesjuan/37gpbuq8/1
  • @JuanMendes "如果第一个参数 (setIng) 发生错误,则不会调用第二个参数 (setError)。" - 这正是这里的理想行为。我们只关心来自getIngredients() 的错误(而且,反应状态设置器从不抛出错误)。使用.catch() 调用并不总是首选。
  • 使用第二个处理程序需要确保它不会引发错误,这可能是因为您尝试调用备份 URL 而导致的错误。我只是说它更安全,行为基本相同。为什么你不希望这种行为在这里?如果处理程序发生错误,您不想让调用者知道吗?它的行为方式与setError 抛出错误的方式不同,它将正确地作为错误传播,如我的链接示例中所示? jsfiddle.net/mendesjuan/37gpbuq8/1
猜你喜欢
  • 2020-11-01
  • 2018-08-19
  • 2021-02-04
  • 2017-01-01
  • 1970-01-01
  • 2018-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多