这并不是一个真正的Apollo问题,它是一个Javascript Promise问题,但是使用了Apollo的示例,因为那是我唯一一次看到它。
Apollo有一个类似this的React钩子:
const { loading, error, data } = useQuery(GET_DOGS);
我了解它如何返回error
-如果承诺解析器抛出错误,则会返回错误。
我了解它如何返回data
-当承诺解析器完成时,它将返回数据。
但是它如何返回loading
,然后又返回data
?我已经编码了许多node.js承诺解析器,还没有看到一种模式,该模式可以在操作进行中返回loading
,然后再返回data
。
哪种Javascript模式使之成为可能?
答案 0 :(得分:3)
他们将使用状态变量,状态变量以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>