Javascript Promise:在 Promise 解决之前返回“正在进行”响应?

Posted

技术标签:

【中文标题】Javascript Promise:在 Promise 解决之前返回“正在进行”响应?【英文标题】:Javascript Promise: Return 'In Progress' Response Until Promise Resolves? 【发布时间】:2020-12-02 10:56:09 【问题描述】:

这不是一个真正的 Apollo 问题,它是一个 javascript 承诺问题,但使用了 Apollo 的一个示例,因为这是我记得唯一一次看到它。

Apollo 有一个类似于 this 的 React 钩子:

const  loading, error, data  = useQuery(GET_DOGS);

我知道它是如何返回 error 的——如果 promise 解析器抛出错误,你会得到一个错误返回。

我了解它如何返回 data -- 当 promise 解析器完成时,它会返回数据。

但是它如何返回loading,然后又返回data?我编写了很多 node.js 承诺解析器,但还没有看到可以在操作过程中返回 loading,然后返回 data 的模式。

什么 Javascript 模式使这成为可能?

【问题讨论】:

这不是一个真正的阿波罗承诺问题。它与 React 挂钩;它可以告诉 React 组件需要重新渲染,这意味着 useQuery 被再次调用并且可以返回 不同的值 【参考方案1】:

他们会使用以true 开头的状态变量,完成后切换到false,大致如下:

function useQuery(/*...*/) 
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [data, setData] = useState(null);

    useEffect(() => 
        let cancelled = false;
        goGetTheStuff()
        .then(data => 
            if (!cancelled) 
                setData(data);
                setLoading(false);
            
        )
        .catch(error => 
            if (!cancelled) 
                setError(error);
                setLoading(false);
            
        );
        return () => 
            cancelled = true;
        ;
    , []);

    return loading, error, data;

现场示例:

const useState, useEffect = React;

function goGetTheStuff() 
    return new Promise((resolve, reject) => 
        setTimeout(() => 
            if (Math.random() < 0.7) 
                // Emulate success
                resolve(data: "here");
             else 
                // Emulate failure
                reject(new Error("Couldn't get the data"));
            
        , 800);
    );


function useQuery(/*...*/) 
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [data, setData] = useState(null);

    useEffect(() => 
        let cancelled = false;
        goGetTheStuff()
        .then(data => 
            if (!cancelled) 
                setData(data);
                setLoading(false);
            
        )
        .catch(error => 
            if (!cancelled) 
                setError(error);
                setLoading(false);
            
        );
        return () => 
            cancelled = true;
        ;
    , []);

    return loading, error, data;


function Example() 
    const loading, error, data = useQuery();
    return (
        <div>
            <div>loading: JSON.stringify(loading)</div>
            <div>data: data && JSON.stringify(data)</div>
            <div>error: error && error.message</div>
        </div>
    );


ReactDOM.render(<Example/>, document.getElementById("root"));
<div>70% of the time when you run this, the async operation succeeds; 30% of the time, it fails. Run repeatedly if you want to see both scenarios.</div>
<hr>
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

【讨论】:

以上是关于Javascript Promise:在 Promise 解决之前返回“正在进行”响应?的主要内容,如果未能解决你的问题,请参考以下文章

使用Promise代替进行回调

Promise的使用

图解 Promise 实现原理—— 基础实现

通过 ES6 Promise 和 jQuery Deferred 的异同学习 Promise

ES6 - Promise 对象

jquery的promise和es6的promise的区别