【问题标题】:How to return a closure from an async function and assign it to useState?如何从异步函数返回闭包并将其分配给 useState?
【发布时间】:2022-01-17 18:41:01
【问题描述】:

我正在尝试从异步函数返回一个函数(闭包)。到目前为止,我拥有 space 的方式始终是一个承诺而不是一个函数,即使它应该是一个闭包。

// ...
    const [space, set_space] = React.useState(false);
    React.useEffect(
    () => {
        API.SERVER(query, PAGE_SIZE)
        .then(response => set_space(response));
    },
    [query]
    );

    React.useEffect(
    () => {
        console.log(space.constructor);
        if (space) {
        space(page)
            .then(response => set_titles(Array.from(response.data)));
        }
    },
    [space, page]
    );
// ...

API

// ...
export default {
    SERVER:async function(search, width)
    {
        if (!search) {
        // return () => {};
        search = DEFAULT_QUERY;
    }
    const all = (await axios.get(SEARCH_URL + `?search=${search}`)).data;
    console.log(all);
    const pages = chunk(all, width);
    // function pager(results) {
    //     const dex = (results > width ? results / width : 0);
    //     const next = pages[dex];
    //     return axios.get(SEARCH_URL + `?fromids=${next}`);
    // }
    // return pager;
    return function(results) {
        const dex = (results > width ? results / width : 0);
        const next = pages[dex];
        return axios.get(SEARCH_URL + `?fromids=${next}`);
    };
    // return pager;
}
};

space.constructor 说它是一个 Promise,但它应该是一个返回 axios 的 Promise 的函数,而不是它自己的 Promise。我无法真正改变 API 的设置方式,因为我需要保持索引客户端,然后通过更改空间的参数来遍历它。

【问题讨论】:

  • 如果您有一个返回值的函数,那么添加async 自动意味着它返回该值的Promise
  • 我不明白space 怎么可能是一个承诺。它是 falseAPI.SERVER(…) 返回的 pager 函数(混淆地也称为 response)。您在哪里以及如何登录/检查space.constructor?您是否遇到某种错误?
  • @Bergi 这对我来说也没有意义。早些时候,我有 SERVER return function(results) // ... 并且使用这种样式它不会立即崩溃,所以我可以在第二个 useEffect 中调用 space.constructor。
  • 嗯,“space is not a function”是意料之中的,因为您使用false 初始化您的状态,这不是函数。但这与异步函数返回的闭包无关。
  • 你能分享一个minimal reproducible example吗?我仍然不相信console.log(space.constructor); 会用你发布的代码打印Promise

标签: javascript reactjs async-await


【解决方案1】:

问题是,set_space 处理函数的方式与其他值不同。

这是因为 React 的状态设置器可以接受一个回调,该回调接收之前的状态作为参数。

但是,React 无法区分回调和恰好是函数的值。因此,React 会假定它是一个回调并调用它,然后将状态设置为包含它的返回值,即另一个 Promise。

要将函数本身置于状态,您可以创建一个返回函数的回调,如下所示:

API.SERVER(query, PAGE_SIZE)
.then(response => set_space(() => response));

【讨论】:

  • 我忘记了 useState。这让我面对手掌。谢谢。
  • @JohnSmith 将函数存储到状态并不是一件常见的事情,所以很容易错过......
【解决方案2】:

嗯...您只想要一个在调用时返回您承诺的函数吗?那么useCallback呢?

const triggerAsync = React.useCallback(
    () => {
        return API.SERVER(query, PAGE_SIZE)
        .then(response => set_space(response))
    },
    [query]
    );

triggerAsync 应该在你执行它时返回一个承诺

【讨论】:

    猜你喜欢
    • 2020-12-09
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2018-10-29
    • 2020-07-29
    • 2023-03-08
    相关资源
    最近更新 更多