简单理解|简单理解 Javascript 中的异步
异步是什么?
异步是相对于同步而言的,同步就是一行一行代码执行下去,异步呢就是分成多个任务同时执行。
举个例子:
西游记中大闹五庄观一回里,童子大骂唐僧师徒是偷果子的秃贼,孙悟空气的脸涨得通红,但又不能当师父面发作,于是真身出神,到园子里把人参果树推倒,没留一个果子,完事毫毛一收,趁着夜色解开门锁,带着师徒一行人逃跑了。这里的猴子,本体还在挨骂受气呢,结果分身跑去铲果树了,这就是个异步的过程。
异步是怎么实现的? javascript 不是单线程的吗,那么它是如何实现异步的呢?
如果你在加班的时候,外卖到了,你会怎么做呢?自己去拿,工作思路会被打断。像孙悟空一样分身,那不现实。好在公司不止一个人,我们可以叫其他同事帮忙拿一下,拿到外卖后告诉我们一声,然后我们就可以愉快的用餐了。
【简单理解|简单理解 Javascript 中的异步】JS 也是如此,虽然它是单线程的,只能同时处理一件事,但是主线程可以发起一个异步请求,相应的工作线程就会接收这个请求并进行处理,等到工作线程的处理有了结果,浏览器就会通知主线程,刚才的请求已经完成,结果已经拿到了,可以执行回调函数,处理异步获得的结果。
如何编写异步代码? 最合理的方式是通过 Promise 对象。
举个例子,我们来看看它是怎么用的。
上个月小舅子向我借了点钱,今天偶然碰到他,我便问他什么时候能还钱,他说下个月发了工资就还我。我说不行啊,下个月我要出差。他说:这样吧,姐夫,你告诉我,你打算用这笔钱做什么,我替你去做。虽然我表示怀疑,但也只能接受了,毕竟我还有别的事情要去做,不可能一直等着他变出钱来。把上面的情景用代码表示,就像这样:
于是我跟他说:好吧。那下个月你直接把欠我的钱,交到我的老婆那里好了。小舅子爽快的答应了。
// Promise 对象
let 小舅子的承诺 = new Promise((答应的事情) => {
setTimeout(() => {
let 工资 = 2000;
// 发工资了
let 要还的钱 = 工资 * 0.5;
// 拿出一半还账
答应的事情(要还的钱);
// 处理姐夫的委托
}, 30 * 100);
// 30 天后...
});
// 回调函数
function 我的请求(一笔钱) {
console.log('把' + 一笔钱 + '上交给老婆');
}// then 指定回调函数
小舅子的承诺.then(我的请求);
// 小舅子答应了我的请求// 3秒后打印:把1000上交给老婆
async/await 是什么? JS 的语法糖而已,可以让你从回调函数中解放出来。
还是以上面的情景为例,假如我打算拿这钱去做个按摩...像这种事绝对不能和小舅子说,要是我老婆要是知道了话,肯定会把我活剥了。那就让小舅子把要还的钱直接打我银行卡里,我就等银行的到账通知就行了。也不耽误我的工作,又不用告诉小舅子我的计划,而且我可以自由的安排资金的用途。写成代码的话就像这样:
// Promise 对象
let 小舅子的承诺 = new Promise((答应的事情) => {
setTimeout(() => {
let 工资 = 2000;
// 发工资了
let 要还的钱 = 工资 * 0.5;
// 拿出一半还账
答应的事情(要还的钱);
// 处理姐夫的委托
}, 30 * 100);
// 30 天后...
});
// 异步函数
async function 我的计划() {
// 用了 await 委托就变成了:无需处理直接转账给我
let 一笔钱 = await 小舅子的承诺;
// 等待小舅子转账
console.log('拿' + 一笔钱 + '去做个按摩');
};
// 调用异步函数
我的计划();
// 3秒后打印:拿1000去做个按摩
两种写法有什么区别吗? 都是基于 Promise 对象,只不过一个用 then 方法指定回调函数,一个用 await 获取 resolve 的值(其实就是参数本身)。需要注意的是 await 需要写在异步函数中(思考下,为什么)。
来做个小练习,可以帮你理解这二者之间的区别。
function get(url, callback) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.onload = function () {
if (req.readyState == 4 && req.status == 200) {
callback(req.response);
}
}
req.send();
}var url = 'https://miao.baidu.com/';
get(url, function (html) {
var re = new RegExp('<[^<>]+>', 'g');
var text = html.replace(re, "");
console.log(text);
});
// 在 miao.baidu.com 页面的控制台中执行
// 打印:Hello World
请参照上面的代码,用 Promise 对象封装一个 get 函数。
通过这个函数访问 miao.baidu.com,并打印去除了所有 HTML 标签后的文本。
要求:使用 then 和 await 两种方法。
推荐阅读
- 深入理解Go之generate
- 考研英语阅读终极解决方案——阅读理解如何巧拿高分
- 由浅入深理解AOP
- 科学养胃,别被忽悠,其实真的很简单
- 事件代理
- 逻辑回归的理解与python示例
- opencv|opencv C++模板匹配的简单实现
- 数组常用方法一
- 松软可口易消化,无需烤箱超简单,新手麻麻也能轻松成功~
- 「按键精灵安卓版」关于全分辨率脚本的一些理解(非游戏app)