async/await和defer详解
骚话王又来分享知识了!今天咱们聊聊前端开发中让人又爱又恨的异步编程,主角就是Promise和它的进阶形态------async/await,还有经常被新手搞混的HTML中的async和defer。要是你觉得有用,记得收藏点赞,骚话鬼才持续输出干货!
Promise:异步编程的"诺言"
在JavaScript的世界里,异步操作无处不在,比如网络请求、定时器、文件读取......早年间大家用回调(callback)解决异步,结果一不小心就掉进了"回调地狱",代码像层层嵌套的俄罗斯套娃,调试起来让人头秃。
Promise横空出世,像是给异步编程打了一针强心剂。它的本质是一个"承诺":我现在还没拿到结果,但我保证将来某一刻会给你答复(要么成功,要么失败)。
Promise的基本用法
举个栗子:
js
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('骚话王的承诺兑现了!');
}, 1000);
});
promise.then(result => {
console.log(result); // 输出:骚话王的承诺兑现了!
});
Promise让异步代码变得更清晰,但链式调用多了,依然容易让人晕头转向。
骚话王小贴士: Promise有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。状态一旦改变就不会再变。
async/await:让异步像同步一样丝滑
骚话王要说,async/await就是Promise的"语法糖",让你写异步代码像写同步一样顺滑。async函数返回的本质还是Promise,但你可以用await
暂停代码执行,等Promise有结果再往下走。
async的用法
只要在函数前加上async
,这个函数就会自动返回一个Promise。
js
async function foo() {
return '骚话王又来啦!';
}
foo().then(res => console.log(res)); // 输出:骚话王又来啦!
await的魔力
await
只能在async函数里用,它会"等待"Promise的结果,代码看起来就像同步一样。
js
async function getData() {
const result = await promise;
console.log(result); // 输出:骚话王的承诺兑现了!
}
getData();
是不是很丝滑?再也不用写一堆.then()
,也不用担心回调嵌套。
错误处理也优雅
用try/catch包裹,异步错误也能像同步一样捕获。
js
async function fetchData() {
try {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
console.log(data);
} catch (err) {
console.error('骚话王捕获到错误:', err);
}
}
骚话王小贴士: await后面可以接任何Promise对象,也可以接普通值,普通值会被自动包装成已resolve的Promise。
async/await和Promise的关系
记住,async/await不是替代Promise,而是让Promise更好用。它们是"亲兄弟",async/await只是让你写代码更优雅。
常见误区提醒: async/await不能脱离Promise单独存在,await只能在async函数里用。
html中的async和defer小科普
顺带一提,defer
和async
是script标签的两个属性,和js的async/await没啥直接关系,但经常被新手搞混。它们的作用都是优化外部JS脚本的加载和执行时机,避免页面渲染被阻塞。
骚话王这里给大家掰扯掰扯浏览器加载JS时的"阻塞"机制:
-
普通的
<script src="...">
:浏览器解析到script标签时,会立刻暂停(阻塞)HTML的解析,去下载并执行JS,等JS执行完了才继续解析后面的HTML。这就像你正写作业,突然被喊去倒垃圾,必须干完才能回来继续。 -
<script src="..." defer>
:加了defer后,浏览器遇到script标签不会立刻执行,而是等到HTML文档解析完毕(DOMContentLoaded事件前)再统一顺序执行所有defer脚本。这样页面内容能更快显示,用户体验更好。 -
<script src="..." async>
:async和defer有点像,但async脚本下载完就立刻执行(不等HTML解析),执行时同样会阻塞HTML解析,但多个async脚本执行顺序不确定。
举个例子:
html
<!-- 阻塞型 -->
<script src="a.js"></script>
<p>骚话王的段落</p>
<!-- defer型 -->
<script src="b.js" defer></script>
<p>骚话王的段落</p>
如果a.js很大,页面会卡在script标签那里,p标签内容迟迟不显示;而b.js用defer,p标签能立刻渲染出来,b.js等HTML都解析完再执行。
骚话王友情提醒:
- defer和async只对外部脚本有效,内联脚本用不了。
- defer和async不能同时用,选一个就行。
- 多个defer脚本会按顺序执行,多个async脚本顺序不确定。
- 推荐将重要依赖脚本用defer,统计类脚本用async。
Promise是异步的基石,async/await让异步代码优雅如诗。html中的async和defer则是前端性能优化的利器。学会这套组合拳,异步编程和页面性能再也不是拦路虎!
如果觉得骚话鬼才的分享有用,别忘了点赞收藏,关注我,持续解锁更多前端骚操作!