简体   繁体   中英

Javascript Promise: Return 'In Progress' Response Until Promise Resolves?

This isn't really an Apollo question, it's a Javascript promises question, but uses an example from Apollo, because that's the only time I recall seeing it.

Apollo has a React hook that looks like this :

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

I understand how it returns error -- if the promise resolver throws an error, you get an error back.

I understand how it returns data -- when the promise resolver completes, it returns the data.

But how does it return loading and then later return data ? I've coded quite a few node.js promise resolvers and haven't yet seen a pattern that could return loading while the operation is in process, and then later return the data .

What Javascript pattern makes this possible?

They'd use a state variable that starts true and is switched to false when they're done, vaguely like this:

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

Live Example:

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM