最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
资料预览
给大家整理的视频资料:
给大家整理的电子书资料:
如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
四、JWT、用户认证与异步请求
五、CSS 其实很简单 - 用 CSS-in-JS 添加样式
六、用户体验优化 - 加载中和错误状态处理
1~2
3.登录注册页面 Loading 和 Error 状态处理,与 Event Loop 详解
列表页的 异步状态 弄完,接下来是登录注册页了
修改 src\unauthenticated-app\index.tsx
(新增 error
状态处理,将 error
j监听操作 交给 登录注册页):
...
import { Card, Button, Divider, Typography } from "antd";
...
export const UnauthenticatedApp = () => {
...
const [error, setError] = useState<Error | null>(null);
return (
<Container>
...
<ShadowCard>
<Title>{isRegister ? "请注册" : "请登录"}</Title>
{ error ? <Typography.Text type="danger">{error.message}</Typography.Text> : null }
{isRegister ? <Register onError={setError}/> : <Login onError={setError}/>}
<Divider />
...
</ShadowCard>
</Container>
);
};
...
修改 src\unauthenticated-app\login.tsx
(传入 onError
并在异步操作后 catch
中使用):
...
export const Login = ({onError}: { onError: (error: Error) => void }) => {
...
const handleSubmit = (values: { username: string; password: string }) => {
login(values).catch(e => onError(e))
};
...
};
...
同理修改 src\unauthenticated-app\register.tsx
:
...
export const Register = ({onError}: { onError: (error: Error) => void }) => {
...
const handleSubmit = (values: { username: string; password: string }) => {
register(values).catch(e => onError(e))
};
...
};
...
使用非预设用户名密码检验:没反应。。。但是控制台打印出了刚输入的用户名和密码。。。
通过登录的调用链可以找到 导致这个问题的原因:src\auth-provider.ts
!res.ok
时,返回了Promise.reject(data)
,而data
是请求入参,这显然不是预想的效果(注册同理),修改这部分为Promise.reject(await res.json())
修改后再次检验,成了!
Promise.catch
固然好用,但接下来换个思路,使用 try..catch
并引出 Event Loop
。
先修改 src\unauthenticated-app\login.tsx
试试水:
...
export const Login = ({onError}: { onError: (error: Error) => void }) => {
...
const handleSubmit = (values: { username: string; password: string }) => {
try {
// login(values).catch(e => onError(e))
login(values);
} catch(e: Error | any) {
onError(e)
}
};
...
};
...
控制台输出正常,但是界面没有效果。。。
问题出在 login 是异步操作,程序中会优先执行同步操作,然后才会异步操作,所以 onError 优先执行,并没有拿到后端返回的报错信息
再次修改 src\unauthenticated-app\login.tsx
(使用 async await 处理异步操作):
...
export const Login = ({onError}: { onError: (error: Error) => void }) => {
...
const handleSubmit = async (values: { username: string; password: string }) => {
try {
// login(values).catch(e => onError(e))
await login(values);
} catch(e: Error | any) {
onError(e)
}
};
...
};
...
这样便正常啦!
接下来给注册页新增确认密码功能
修改 src\unauthenticated-app\register.tsx
(新增确认密码的 Form.Item
和 相关处理逻辑):
...
export const Register = ({onError}: { onError: (error: Error) => void }) => {
const { register, user } = useAuth();
const handleSubmit = ({ cpassword, ...values }: { username: string, password: string, cpassword: string }) => {
if (cpassword === values.password) {
register(values).catch(e => onError(e));
} else {
onError(new Error('请确认两次的输入密码相同'))
return
}
};
return (
<Form onFinish={handleSubmit}>
<Form.Item
name="username"
rules={[{ required: true, message: "请输入用户名" }]}
>
<Input placeholder="用户名" type="text" id="username" />
</Form.Item>
<Form.Item
name="password"
rules={[{ required: true, message: "请输入密码" }]}
>
<Input placeholder="密码" type="password" id="password" />
</Form.Item>
<Form.Item
name="cpassword"
rules={[{ required: true, message: "请确认密码" }]}
>
<Input placeholder="确认密码" type="password" id="cpassword" />
</Form.Item>
<Form.Item>
<LongButton htmlType="submit" type="primary">
注册
</LongButton>
</Form.Item>
</Form>
);
};
再接着为 登录注册页 添加异步状态 Loading
的处理:
...
import { useAsync } from "utils/use-async";
export const Login = ({onError}: { onError: (error: Error) => void }) => {
const { login, user } = useAuth();
const { run, isLoading } = useAsync()
const handleSubmit = async (values: { username: string; password: string }) => {
try {
// login(values).catch(e => onError(e))
await run(login(values))
} catch(e: Error | any) {
onError(e)
}
};
return (
<Form onFinish={handleSubmit}>
...
<Form.Item>
<LongButton loading={isLoading} htmlType="submit" type="primary">
登录
</LongButton>
</Form.Item>
</Form>
);
};
...
检验一下,没有效果,但是控制台抛出 400 错误了,排查一下
try..catch
中的onError
没接收到,唯一的变数就是这个run
了- 查看一下,果然报错被
run
内部消化了,没有正常抛出(将catch
到的error throw
或是用Promise.reject
包裹返回都是可以的,建议使用后者)
修改 src\utils\use-async.ts
:
...
export const useAsync = <D>(initialState?: State<D>) => {
...
// run 来触发异步请求
const run = (promise: Promise<D>) => {
...
return promise
.then(...)
.catch((error) => {
// catch 会消化异常,如果不主动抛出,外面是接收不到异常的
setError(error);
// return error; // 原代码
// throw error;
return Promise.reject(error);
});
};
...
};
检验一下,正常 catch
并 展示报错信息
- try…catch only works for runtime errors (try…catch 只能处理有效代码之中的异常)
- try…catch works synchronously(try…catch 只能处理同步代码之中的异常)
问题是解决了,但这样 try…catch 还是有些拖泥带水的感觉,继续优化:
修改 src\utils\use-async.ts
(增加是否抛出异常的配置,来合理化逻辑):
...
const defaultConfig = {
throwOnError: false
}
export const useAsync = <D>(initialState?: State<D>, initialConfig?: typeof defaultConfig) => {
const config = {...defaultConfig, ...initialConfig}
...
// run 来触发异步请求
const run = (promise: Promise<D>) => {
...
return promise
.then((data) => {
setData(data);
return data;
})
.catch((error) => {
// catch 会消化异常,如果不主动抛出,外面是接收不到异常的
setError(error);
return config.throwOnError ? Promise.reject(error) : error;
});
};
...
};
修改 src\unauthenticated-app\login.tsx
(传入 { throwOnError: true }
):
...
export const Login = ({onError}: { onError: (error: Error) => void }) => {
...
const { run, isLoading } = useAsync(undefined, { throwOnError: true })
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
最全的Linux教程,Linux从入门到精通
======================
1. **linux从入门到精通(第2版)**
2. **Linux系统移植**
3. **Linux驱动开发入门与实战**
4. **LINUX 系统移植 第2版**
5. **Linux开源网络全栈详解 从DPDK到OpenFlow**
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
a27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**