异步与 Promise
异步与 Promise
即 JS 异步编程模型
异步与同步
如果能直接拿到结果就是同步
比如在医院挂号,你拿到号才会离开窗口
同步任务可能消耗时间长,也可能短
总之不拿到结果是不会离开的
如果不能直接拿到结果就是异步
比如在餐厅门口等位,拿到号可以先去逛街
什么时候才能吃到饭?
你可以每 10 分钟去餐厅问一下(轮询)
你也可以扫码用微信小程序接收通知(回调)
异步举例
以 AJAX 为例
request.send() 之后,并不能直接得到 response
不信可以使用 console.log(request.response) 测试
必须等到 readyState 变为 4 后,浏览器回头调用 request.onreadystatechange 函数
才能得到 request.response (完整的)
这跟餐厅发送微信提醒的过程类似
回调 callback
写给自己用的函数,不是回调
写给别人用的函数,就是回调
request.onreadystatechange 就是我写给浏览器调用的
意思就是让浏览器回头调一下这个函数
这里的“回头”指的是将来的意思
写了却不调用,给别人调用的函数,就是回调
回调举例
** **把函数 1 给另一个函数 2
1 |
|
这里我创建了 f1 但并没有调用 f1
我把 f1 传给了 f2 (别人)
f2 调用 f1 了
f1 是我写给 f2 调用的函数
所以 f1 是回调
1 |
|
fn’(‘你好’)中的 fn 就是 f1
fn(‘你好’) 中的 ‘你好’ 会被赋值给参数 x
异步和回调的关系
关联
异步任务需要在得到结果时通知 JS 来拿结果
可以让 JS 留一个函数地址(电话号码)给浏览器
异步任务完成时浏览器调用该函数地址即可(拨电话)
同时把结果作为参数传给该函数(电话里说可以来了)
这个函数是我写给浏览器调用,所以是回调函数
区别
异步任务需要用到回调函数来通知结果
异步常常用到回调但不一定非要回调,还有轮询
回调函数不一定只用在异步任务里
回调可以用到同步任务里
1 |
|
判断异步与同步
如果一个函数的返回值处于
setTimeout
AJAX(即 XMLHttpRequest)
AddEventListener
这三个东西内部,那么这个函数就是异步函数
举例
1 |
|
摇骰子() 没有写 return ,就是 return undefined
箭头函数里有 return ,返回真正的结果
所以这是一个异步函数/异步任务
返回值
1 |
|
使用回调,写个函数然后把函数地址给它
1 |
|
简化为箭头函数
由于 f1 声明之后只用了一次,所以可以删掉 f1
1 |
|
还能简化成
1 |
|
!如果参数不一致就不能这样简化
比如
1 |
|
parseInt 的参数与 map 的参数不一致所以不能简写
1 |
|
总结
异步任务不能直接拿到结果
可以传一个回调给异步任务
异步任务完成时调用回调
调用的时候把结果作为参数
异步任务两个结果时
方法一:回调接收两个参数
1 |
|
方法二:
1 |
|
!使用以上两种方法有三个缺点
一、不够规范,名称太多,有人用 success + error 有人用 done + fail
二、容易出现回调地狱,代码变得看不懂
三、很难进行错误处理**
解决方法:
一、规范回调的名字或顺序
二、拒绝回调地狱,让代码可读性更强
三、很方便地捕获错误
1 |
|
1 |
|
小结
第一步
1 |
|
第二步
使用.then(success,fail) 传入成功和失败函数
上面封装的 ajax 的缺点
post 无法上传数据
1 |
|
不能设置请求头
1 |
|
可以选择把 ajax 写到完美
或使用 jQuery.ajax (几近完美)/ axios