rxjs 异步调用
Now that React Hooks have been officially released, even more patterns are emerging across the Internet.
现在, React Hooks正式发布了,互联网上出现了更多的模式。
useEffect (useEffect)
The useEffect
hook’s among the most popular, as it can replace componentDidMount
, componentDidUpdate
, and componentWillUnmount
.
useEffect
钩子是最受欢迎的钩子,因为它可以替换componentDidMount
, componentDidUpdate
和componentWillUnmount
。
Most of the initialization, updates, and cleanup logic a component may need can be put inside of useEffect
.
组件可能需要的大多数初始化,更新和清除逻辑都可以放在useEffect
。
丑陋的用户体验 (An Ugly User Experience)
On a recent project, I encountered a scenario where useEffect
acted on HTTP requests I was no longer interested in.
在最近的项目中,我遇到了一个场景,其中useEffect
对我不再感兴趣的HTTP请求起作用。
Conceptually, the UI was like this:
从概念上讲,UI如下所示:
![](https://i-blog.csdnimg.cn/blog_migrate/ca6a0db429f30f439960778b7aef9070.png)
On first load, fetch the list of fruits and render a
<button>
for each one.第一次加载时,获取水果列表并为每个水果渲染一个
<button>
。Click a
<button>
to fetch that fruit’s details.单击
<button>
以获取该水果的详细信息。
But watch what happens when I click multiple fruits in a row
但是请注意当我连续单击多个水果时会发生什么
![](https://i-blog.csdnimg.cn/blog_migrate/1d501dfb13211fecb891da6cf0be6462.gif)
Way after I stopped clicking, the fruit detail section kept changing!
我停止点击后的方式,水果详细信息部分不断变化!
代码 (The Code)
Let’s see my custom hook that leverages useEffect
.
让我们看看利用useEffect
自定义钩子。
Here’s the Codesandbox and GitHub links if you wish to follow along. The file is useFruitDetail.js
.
如果您想继续,这里是Codesandbox和GitHub链接。 该文件是useFruitDetail.js
。
import { useEffect, useState } from 'react';
import { getFruit } from './api';
export const useFruitDetail = (fruitName) => {
const [fruitDetail, setFruitDetail] = useState(null);
useEffect(() => {
if (!fruitName) {
return;
}
getFruit(fruitName).then(setFruitDetail);
}, [fruitName]);
return fruitDetail;
};
Whenever fruitName
changes, we’ll request its details. And we have no way of cancelling a request! So quickly re-running this results in many state changes that we’re no longer interested in.
每当fruitName
更改时,我们都将请求其详细信息。 而且我们无法取消请求! 因此,快速重新运行此操作会导致许多状态更改,而我们不再对此感兴趣。
If you render this to the UI, you get a messy user experience where the detail section keeps flickering until the final request is resolved.
如果将其呈现到UI,您将获得混乱的用户体验,其中详细信息部分会一直闪烁,直到最终请求得到解决。
输入RxJS (Enter RxJS)
Ignoring old requests is trivial with RxJS.
使用RxJS可以忽略旧的请求。
It can do so much more than what I’ll demo here, so I highly recommend you dive into it!
它可以做的比我在此演示的要多得多,因此我强烈建议您深入学习 !
This portion of our code, the effect code, needs to change.
我们这部分代码( 效果代码)需要更改。
() => {
if (!fruitName) {
return;
}
getFruit(fruitName).then(setFruitDetail);
};
Instead of a Promise, let’s convert getFruit
into an Observable using the RxJS defer
function. And instead of .then
, we’ll call .subscribe
.
让我们使用RxJS defer
函数将getFruit
转换为Observable,而不是Promise。 而代替.then
,我们会打电话给.subscribe
。
import { defer } from 'rxjs';
// ...
() => {
if (!fruitName) {
return;
}
defer(() => getFruit(fruitName)).subscribe(setFruitDetail);
};
This doesn’t fix the issue yet. We still need to unsubscribe if fruitName
changes.
这还不能解决问题。 如果fruitName
更改,我们仍然需要退订 。
According to React’s docs, we can return a function that’ll be executed at the end of our effect. This acts as the cleanup logic.
根据React的文档 ,我们可以返回一个将在效果结束时执行的函数。 这充当清理逻辑。
So something like this:
所以像这样:
() => {
if (!fruitName) {
return;
}
const subscription = defer(() => getFruit(fruitName)).subscribe(
setFruitDetail
);
return () => {
subscription.unsubscribe();
};
};
有用! (It Works!)
![](https://i-blog.csdnimg.cn/blog_migrate/093ca9b375552130ffd516ee3eb9295f.gif)
This experience is much cleaner!
这种经验要干净得多!
By clicking another fruit, useEffect
sees fruitName
change and runs the previous effect’s cleanup logic. As a result, we unsubscribe from the previous fetch call and focus on the current one.
通过单击另一个水果, useEffect
将看到fruitName
更改并运行前一个效果的清理逻辑。 结果,我们取消了上一个提取调用的订阅,并专注于当前调用。
Now our UI patiently waits until the user’s done clicking and the latest fruit’s details return.
现在,我们的用户界面耐心等待,直到用户单击完毕并返回最新水果的详细信息。
Thanks for following this tutorial to the end!
感谢您结束本教程的学习!
翻译自: https://www.freecodecamp.org/news/how-to-easily-cancel-useeffect-http-calls-with-rxjs-d1be418014e8/
rxjs 异步调用