1. 发请求和得到响应的时间范围
在JS里面,发一个网络请求,再成功得到响应,大概就是几百毫秒到1,2秒之间。
2. 回调
写了却不调用,给别人调用的函数,就是回调
//举例:
function f1() {}
function f2(fn) {
fn()
}
f2(f1)// f2是我自己调用的,所以f2不是回调,f1是我写给f2调用的函数
3. 异步函数
function play() {
setTimeout(()=>{
return parseInt(Math.random() * 6) + 1
},1000)
//return undefined
}
//play()没有写return,那就是return undefined
//箭头函数里有return,返回真正的结果
//所以这是一个异步函数/异步任务
const n = play()
console.log(n) //undefined
4.异步和回调的关系
-
关联
异步任务需要在得到结果时通知 JS 来拿结果,怎么通知呢?
- 可以让 JS 留一个函数地址(电话号码)给浏览器
- 异步任务完成时浏览器调用该函数地址即可(拨打电话)
- 同时把结果作为参数传给该函数(电话里说可以来吃了)
- 这个函数是我写给浏览器调用的,所以是回调函数
- 区别
- 异步任务需要用到回调函数来通知结果
- 但回调函数不一定只用在异步任务里
- 回调可以用到同步任务里
- array.forEach( n => console.log(n) ) 就是同步回调
5. 如何拿到异步结果
//可以用回调。写个函数,然后把函数地址给它
function f1(x) {console.log(x)}
play(f1)
//然后我要求play函数得到结果后把结果作为参数传给f1
function play(fn) {
setTimeout(()=>{
fn(parseInt(Math.random() * 6) + 1)
},1000)
}
6. 面试题
const array = ['1', '2', '3'].map(parseInt)
console.log(array)
//等价于
const array2 = ['1','2','3'].map((item,i,arr)=>{
return parseInt(item,i,arr)
//parseInt('1',0,arr) =>1
//parseInt('2',1,arr) =>NaN 1进制里面没有2
//parseInt('3',2,arr) => NaN 2进制里面没有3
})
console.log(array2)
const array1 = ['1','2','3'].map((item,i,arr)=>{
return parseInt(item)
})
console.log(array1)
const array3 = ['1','2','3'].map((item,i,arr)=>parseInt(item,i,arr));
console.log(array3)
7. 总结
异步任务不能拿到结果
于是我们传一个回调给异步任务
异步任务完成时调用回调
调用的时候把结果作为参数
8. 封装简易版ajax.js
ajax = (method,url,options) => {
const {success,fail} = options //析构赋值
const request = new XMLHttpRequest()
request.open(method,url)
request.onreadystatechange =()=>{
if(request.readyState === 4) {
//成功旧调用success,失败就调用fail
if(request.status < 400) {
success.call(null,request.response)
} else if(request.status >= 400) {
fail.call(null,request,request.status)
}
}
}
request.send()
}
ajax('get','/xxx',{
success(response){},fail: (request,status)=>{}
}) //左边是 function 缩写,右边是箭头函数
//success:function(response)
9.封装简易版ajax.js改为promise.js
如何让一个回调的异步函数变成promise的异步函数:
第一步
- return new Promise((resolve,reject)=>{...})
- 任务成功则调用 resolve(result)
- 任务失败则调用 reject(error)
- resolve 和 reject 会再去调用成功和失败函数
第二步
- 使用 .then(success, fail) 传入成功和失败函数
ajax = (method, url, options) => {
return new Promise((resolve, reject) => {
const {
success,
fail
} = options //析构赋值
const request = new XMLHttpRequest()
request.open(method, url)
request.onreadystatechange = () => {
if (request.readyState === 4) {
//成功就调用resolve,失败就调用reject
if (request.status < 400) {
resolve.call(null, request.response)
} else if (request.status >= 400) {
reject.call(null, request, request.status)
}
}
}
request.send()
})
}
ajax('get', '/xxx').then((response) => {}, (request) => {})
10. 使用axios
axios.get('/5.json')
.then(response=>
console.log(response)
)
参考资料:饥人谷