最近在公司实习写的是es5,在和回调地狱经过一番拉扯之后写下这篇文章,也算是体验了一把没有promise的时代
假设我们的div有一个日历列表,但是由于大小关系只能每次显示2天的信息,项目限制只能使用es5,不能使用es6的promise,且后端给我们的接口只能每次请求一个具体日期的数据
例如
getDateInfo(2023,7,26)
//return
{
date:'12',
lunar:'五月廿五',
weekday:'周六'
}
现在的需求是首屏加载2个item,有些人会觉得这还不简单吗,先请求第一个,再在回调里面请求第二个
确实如此,那假如我们有20个,200个item呢,就会掉入回调地狱,还有一个问题就是前面的请求失败会导致后面的请求无法执行(即使后面的请求单独可用)
那么此时我们就需要
并发请求
首屏加载的onload中同时请求两次
getListItem(date) {
var success = function(res) {
console.log(res.date)
//更新数据和视图
}
getDateInfo(2023,7,date,success)
getDateInfo(2023,7,date+1,success)
}
getListItem(date)
那么新的问题来了,我们的日期列表需要按顺序展示,但是我们本地的数组是通过请求回来再在回调里存到数组中的,
由于网络的不可控性,我们不知道哪个请求会先被返回回来,那么如何保证顺序呢
错误做法:
使用闭包传参,在回调中用参数当索引修改数组,例如上面传的date和date+1,因为在执行回调的时候所有同步代码已经执行完毕,既然传的是同一个回调函数的地址,那么找到的是同一个作用域,里面的date已经递增完毕,所以所有回调取到的都是date+1,也就是最后一个传入值
es5保证回调顺序的两种正确方式
1.接口返回我们传入的参数,或者能当作顺序标识符号的属性,例如id,然后我们在给数组赋值的时候,对id做处理得出数据先后顺序的索引index,再用arr[index]为数组赋值,因为是返回的数据,所以总能取到正确的值,这种方式要求接口要返回对应的标识或者顺序属性,不过绝大部分接口都会有
2.给每一个请求传入不同的回调函数(引用地址不同),例如
var success1 = function(res) {
console.log(res.date)
//更新数据和视图
}
var success2 = function(res) {
console.log(res.date)
//更新数据和视图
}
getDateInfo(2023,7,date,success1)
getDateInfo(2023,7,date+1,success2)
那么我们就可以在各自的回调函数中写入固定的索引去更新数据和视图,而不是使用index这种变量作为索引,但是这种方式会增加代码量,会产生许多重复的冗余代码
如果有别的可以保证返回顺序的方式,欢迎评论区讨论
本文由Escaay原创,转载请注明出处