React中如何处理承诺demo
Jovie 人气:0正文
诺言本质上是一种处理异步操作的方式,一个常见的例子是在React中执行API请求。为了在React生命周期中使用这些操作,我们可以使用useState钩子来存储承诺的结果,当它被解决并重新渲染组件。
本教程假设你熟悉React中钩子的使用,所以如果你不确定,请查看我们的介绍
什么是 "承诺"?
诺言允许你在JavaScript中执行异步操作。要从头开始构建一个Promise,你可以使用Promise构造器。这个函数需要两个参数:"resolve",当操作完成时调用的函数,以及 "reject",当操作失败时调用的函数。然后,当你的操作完成时,你必须调用这些函数中的一个。
JavaScript给了你两种处理承诺结果的方法,第一种是 .then(),一个以函数为参数的函数,它将把解决后的值传递给该函数:
const promiseThen = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hi!'); }, 1000); }); promiseThen .then((val) => { console.log(val); }) .catch((err) => console.log(err));
其他的东西都不会等待你的承诺解决,但是你提供给 ***.then()***将在承诺解析时运行。
另一种方法是 "async/await "功能,这通常是首选;如果你 "等待 "一个承诺,代码将停止运行,直到承诺完成。下面是上面的例子,重写后使用了await来代替:
const promiseAwait = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hi!'); }, 1000); }); const result = await promiseAwait; console.log(result);
在React的页面加载中使用承诺
要在React中使用一个Promise的值,你可以使用一个 ***useEffect()***钩子,用一个空的依赖数组来等待承诺的解析,并将结果存储在useState钩子的值中。
下面是一个使用该方法获得一只随机猫的例子,使用CatAAS API:
function PromisesPage() { const [catUrl, setCatUrl] = useState(''); const [error, setError] = useState(false); const [state, setState] = useState(''); useEffect(() => { setState('loading'); axios .get('https://cataas.com/cat?json=true') .then((res) => { console.log(res); setState('success'); setCatUrl('https://cataas.com' + res.data.url); }) .catch((err) => { console.error('Error:', err); setState('error'); setError(err); }); }, []); if (state === 'error') return ( <h1> {error.toString()} </h1> ); return ( <div> <div> {state === 'loading' ? ( <h1>Loading...</h1> ) : ( <img src="{catUrl}" /> )} </div> </div> ); }
当页面加载时,useEffect的函数将被调用。这将使用axios库执行API调用,你可以在这里或这里找到更多信息。当我们的API调用正在进行时,我们会看到一个加载屏幕;这是一个让你的用户了解正在发生什么的好主意。当承诺解决时,我们得到我们所收到的猫,并将其存储在我们的状态中。组件重新渲染,你的猫就被显示出来了
注意:假设你的承诺可能会失败,并为这种可能性做好准备,这是一个好主意。在这种情况下,如果一个错误被抛出,我们会设置一个不同的状态变量,组件会重新渲染,并显示我们的错误信息。
如果你喜欢异步编程的await语法,你可能会发现上面的代码有问题。重写它以使用await,你可以这样写。
useEffect(() => { setState('loading'); try { const res = await axios.get('https://cataas.com/cat?json=true'); setCatUrl(res.data.url); setState('success'); } catch (e) { setError(e); } }, []);
但这将引发一个错误,因为我们试图在一个非异步函数中使用await。我们也不能通过将签名改为 "async () =>"来使useEffect的函数成为异步函数,因为useEffect函数必须是同步的。
useEffect(() => { (async () => { setState('loading'); try { const res = await axios.get('https://cataas.com/cat?json=true'); setCatUrl(res.data.url); setState('success'); } catch (e) { setError(e); } })(); }, []); useEffect(() => { const fetchCat = async () => { setState('loading'); try { const res = await axios.get('https://cataas.com/cat?json=true'); setCatUrl(res.data.url); setState('success'); } catch (e) { setError(e); } }; fetchCat(); }, []);
我们可以用IIFE来解决这个问题,也就是Immediately-Invoked Function Expression。这本质上只是定义了一个函数并立即调用它,这意味着我们可以在useEffect内部的异步函数中等待我们的承诺。
点击时
在上面的例子中,我们必须刷新页面才能得到一只新猫。这有点不方便,所以让我们重构我们的网站,这样我们就可以通过一个按钮获得一只新猫。
function PromisesPage() { const [catUrl, setCatUrl] = useState(''); const [error, setError] = useState(false); const [state, setState] = useState(''); function fetchCat() { setState('loading'); axios .get('https://cataas.com/cat?json=true') .then((res) => { console.log(res); setState('success'); setCatUrl('https://cataas.com' + res.data.url); }) .catch((err) => { console.error('Error:', err); setState('error'); setError(err); }); } useEffect(() => { fetchCat(); }, []); if (state === 'error') return ( <h1> {error.toString()} </h1> ); return ( <div> <div> {state === 'loading' ? ( <h1>Loading...</h1> ) : ( <img src="{catUrl}" /> )} </div> <button> New Cat? </button> </div> ); }
我们把useEffect函数的内容重构为自己的独立函数,这样我们就可以随时触发它了
现在,当我点击按钮时,onClick按钮会触发我们的API请求。当我们的承诺得到解决时,该值被存储在状态中,这就触发了一次重新渲染。
在这个例子中,我使用了一个API调用,但你可以用任何承诺来代替它,不管是像useTimeout这样简单的东西,还是更复杂的东西。如果你喜欢这篇文章,如果我帮助解决了你的问题,或者你有任何问题,请在下面的评论中告诉我。
加载全部内容