1. 同步、异步、回调
同步,能直接拿到结果,并执行下一步操作的
异步,不能直接拿到结果,可以先执行其他操作
异步操作完成,拿到结果后,如何通知?
一种是主动查询,轮询
一种是被动通知,回调
回调,就是自己写好方法,等待异步任务拿到结果后,对方直接执行此方法
满足两点,一是,你自己写的方法;二是,此方法,由另一方调用
比如,AJAX中,监听readyState属性值的变化,是通过浏览器调用XMLHttpRequest对象的onreadystatechange对应的回调,来实现的。
function f(foo) {
setTimeout(() => {
foo(parseInt(Math.random() * 6))
})
}
//第一种写法
function fn(x) { console.log(x) }
f(fn)
//第二种写法
f((x) => { console.log(x) })
//第三种写法
f(console.log)
上述例子,也是通过回调。不同的调用只是函数的简写
PS:注意第三种写法,当函数的参数与使用的参数完全一致时,才可以省略
let arr = ['1', '2', '3'].map(parseInt);
console.log(arr);// [1, NaN, NaN]
parseInt('1',0,arr) // 1
parseInt('2',1,arr) // NaN(parseInt第二个表示几进制)
parseInt('3',2,arr) // NaN(同上)
一般会简单地认为只有item一个参数,所以parseInt(item),可以直接简写。但map本身是由三个参数的map(item,i,arr)
2. 异步与回调的关系
异步与回调只是常见的搭配使用
异步结果可以通过轮询获取,也可以通过回调获得
具体通知过程是,由于JavaScript是单线程,一般都是由浏览器提供的功能进行异步操作,在JavaScript中留下函数地址,异步任务完成时,浏览器调用该函数的地址,同时把该异步任务的结果作为参数传给回调函数,这个函数就是给浏览器使用的,所以是回调函数
同步函数也可以使用回调,arr.forEach((item)=>{console.log(item)}),就是同步回调
3. 异步任务的结果处理
对于异步任务的结果,一般会考虑成功、失败两种场景
下面是对AJAX进行简单的封装
let ajax = (method, url, options) => {
const { success, fail } = options;
const xml = new XMLHttpRequest();
xml.open(method, url);
xml.onreadystatechange = () => {
if (xml.readyState === 4) {
if (xml.status >= 200 && xml.status < 300) {
success.call(null, xml.response)
} else {
fail.call(null, xml)
}
}
}
xml.send()
}
ajax('GET', 'xxx', { success() { }, fail() { } })
若改成Promise的写法
let ajax = (method, url) => {
return new Promise((resolve, reject) => {
const xml = new XMLHttpRequest();
xml.open(method, url);
xml.onreadystatechange = () => {
if (xml.readyState === 4) {
if (xml.status >= 200 && xml.status < 300) {
resolve.call(null, xml.response)
} else {
reject.call(null, xml)
}
}
}
xml.send()
})
}
ajax('GET', 'xxx')
.then(() => { }, () => { })
4. Promise 简介
Promise,异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
- 是一种设计模式
- 成功和失败回调均只接受一个参数
- 任务成功调用
resolve(),resolve再去调用then里的第一个成功回调函数 - 任务失败调用
reject(),reject再去调用then的第二个失败回调函数
Promise的三种状态
pending(待定):初始状态,既没有被兑现,也没有没拒绝fulfilled(已兑现):表示操作成功rejected(已拒绝):表示操作失败
处于待定状态的Promise对象最终结果,要么是fulfilled,要么是rejected。当这些情况发生时,使用then方法里对应的回调函数会被调用
return new Promise((resolve,reject)=>{
})
5. Promise优点
- 对于成功和失败的命名(
success+fail,success+error,done+fail)和写法,定义了统一的标准 - 避免地狱回调,增强代码的可读性
- 便于捕获错误
6. Promise常用方法
Promise.all(iterable),当iterable参数对象中所有的promise对象都成功时,才会触发成功,有一个失败就立即出发失败回调Promise.allSettled(iterable),当iterable参数对象中所有的promise对象都已敲定(settled),即每个promise对象的状态要么是fulfilled,要么是rejected,会返回一个promise。并带有一个对象数组,每个对象对应每个promise的结果Promise.any(iterable),当iterable参数对象中其中的一个promise成功,那就返回这个成功的值Promise.race(iterable),当iterable参数对象中任意一个promise是成功或者失败时,立即将其返回,并触发对应的成功或失败回调
7. Axios
Axios是一个基于 promise 的 HTTP 库,可以用在浏览器和node.js 中。
详细用法可见 Axios中文文档