手把手写:Callback -- 回调地狱
因为js是异步编程的,每执行一次,都会返回一个事件,当返回的事件多了会形成堵塞。称为“回调地狱”。以下面的例子为例
// 回调机制 callback 回调地狱
// 异步编程离不开回调机制 执行-发送请求-绑定事件 执行之后不返回具体的方法怎么绑定事件
var cb = $.Callbacks();
function a(x, y) {
console.log('a', x, y);
}
function b(x, y) {
console.log('b', x, y);
}
cb.add(a, b);
cb.add(a, b);
cb.fire('10', '20'); //fire方法返回一个回调对象到它绑定的回调列表
程序代码输出一次,但执行时却执行了两次,表明这是多余的事件
为了解决多余事件,可以使用unique函数,在Callbacks传一个函数,使它移除重复的元素 定义: $.unique() 函数用于对DOM元素数组进行排序,并移除重复的元素
var cb = $.Callbacks('unique');
function a(x, y) {
console.log('a', x, y);
}
function b(x, y) {
console.log('b', x, y);
}
cb.add(a, b);
cb.add(a, b);
cb.fire('10', '20');
进入重点:回调地狱
css文件:
* {
padding: 0px;
margin: 0px;
}
.tpl {
display: none;
}
.wrapper {
overflow: hidden;
border: 2px solid black;
width: 600px;
margin: 100px auto 0px;
}
.movieSection {
float: left;
width: 180px;
height: 180px;
padding: 10px;
}
.movieSection img {
width: 100%;
height: 150px;
cursor: pointer;
}
.movieSection h3 {
height: 30px;
}
HTML结构:
<!-- 基本结构 -->
<div class="wrapper">
<div class='tpl'>
<img src=""></img>
<h3 class='movieName'></h3>
</div>
</div>
js文件
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type: 'POST',
data: {
userName: 'xjt',
password: '2958'
},
success: function (res) {
console.log(res); //打印出来,才知道传的是什么,需要判断什么
// if(res.data.power)
}
});
我们可以从下图看到,传过来的是权限
如果权限为真,就执行就发送一个VIP网址的请求,
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type: 'POST',
data: {
userName: 'xjt',
password: '2958'
},
success: function (res) {
// console.log(res);
var data = res.data;
if (res.data.power == 'root') {
// vip 网络地址发送请求
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type: 'GET',
success: function (res) {
// console.log(res);
$.each(data, function (index, ele) {
var $MovieSection = $('.tpl').clone().removeClass('tpl')
.addClass('movieSection'); //克隆类名-删除类名-添加类名
//之后要往页面传图片和名字
})
}
})
} else {
// 非VIP
}
}
});
例:传到tpl下的子标签里
如下:
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type: 'POST',
data: {
userName: 'xjt',
password: '2958'
},
success: function (res) {
// console.log(res);
if (res.data.power == 'root') {
// vip 网络地址发送请求
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type: 'GET',
success: function (res) {
// console.log(res);
var data = res.data;
var $Wrapper = $('.wrapper');
$.each(data, function (index, ele) {
var $MovieSection = $('.tpl').clone().removeClass('tpl')
.addClass('movieSection');
//查找它的子标签,再添加图片和名字
$MovieSection.children()
.eq(0).attr('src', ele.poster) //图片属性为poster
.next().text(ele.name); //名字属性为name
// 添加成功后,还需要传给它的父级
$Wrapper.append($MovieSection);
})
}
})
} else {
// 非VIP
}
}
});
从下图可以得知,获取的是第一条数据,那么想知道用户点击的是哪条数据从而返回相应的请求呢?,这时需要用到data方法
如下图:不能把数据加到后面,会获取不到next
需要在它的前面绑定点击事件
如下:
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type: 'POST',
data: {
userName: 'xjt', //后端写好的接口文件属性
password: '2958'
},
success: function (res) {
// console.log(res);
if (res.data.power == 'root') {
// vip 网络地址发送请求
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type: 'GET',
success: function (res) {
// console.log(res);
var data = res.data;
var $Wrapper = $('.wrapper');
$.each(data, function (index, ele) {
var $MovieSection = $('.tpl').clone().removeClass('tpl')
.addClass('movieSection');
$MovieSection.data({
id: ele.id
}).on('click', function () {
console.log($(this).data(
'id')); // 可以在这打印出它们的id,把这些写在数据里
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo',
type: 'GET', //请求方式错了,会请求不到
data: {
movieId: $(this).data('id')
},
success: function (res) {
console.log(res);
}
});
}).children()
.eq(0).attr('src', ele.poster)
.next().text(ele.name)
.data()
// 添加成功后,还需要传给它的父级
$Wrapper.append($MovieSection);
})
}
})
} else {
// 非VIP
}
}
});
如下可以看出可以获取到它的信息,现在需要渲染到页面
接下来要处理成功后的信息:如下: 主演、编剧获取的是一个数组,需要拼成字符串 使用map返回的是一个数组,foreach可以,但返回啥也不是,所以使用reduce遍历,最后返回字符串 ruduce还不熟(需要巩固)
success: function (res) {
var data = res.data; //获取数据
// 再把每个数据单独赋值
var direct = data.direct;
var gut = data.gut;
var mainActor = data.mainActor;
var poster = data.poster;
var screenWriter = data.screenwriter;
var htmlStr = '<div>\
<p>导演:' + direct + '</p>\
<p>剧情:' + gut + '</p>\
<p>主演:' + mainActor.reduce(function (prev, curv) {
console.log(mainActor)
prev += curv + ' '; //加空字符串是为了把名字分开
return prev;
}, '') + '</p>\
<p>编剧' + screenWriter.reduce(function (prev, curv) {
prev += curv + ' ';
return prev;
}) + '</p>\
</div>'
// 创建标签没有样式,可以给它加样式
$(htmlStr).appendTo('body').css({
position: 'absolute',
left: $(window).outerWidth() / 2,
bottom: 100,
width: 400,
marginLeft: -200
})
}
运行如下:点击之后会显示:
附上完整代码:
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type: 'POST',
data: {
userName: 'xjt', //后端写好的接口文件属性
password: '2958'
},
success: function (res) {
// console.log(res);
if (res.data.power == 'root') {
// vip 网络地址发送请求
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type: 'GET',
success: function (res) {
// console.log(res);
var data = res.data;
var $Wrapper = $('.wrapper');
$.each(data, function (index, ele) {
var $MovieSection = $('.tpl').clone().removeClass('tpl')
.addClass('movieSection');
$MovieSection.data({
id: ele.id
}).on('click', function () {
console.log($(this).data(
'id')); // 可以在这打印出它们的id,把这些写在数据里
$.ajax({
url: 'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo',
type: 'GET', //请求方式错了,会请求不到
data: {
movieId: $(this).data('id')
},
success: function (res) {
var data = res.data; //获取数据
// 再把每个数据单独赋值
var direct = data.direct;
var gut = data.gut;
var mainActor = data.mainActor; //这是一个数组,需要拼成字符串 使用map返回的是一个数组,foreach可以,但返回啥也不是,所以使用reduce遍历,最后返回字符串
var poster = data.poster;
var screenWriter = data.screenwriter;
var htmlStr = '<div>\
<p>导演:' + direct + '</p>\
<p>剧情:' + gut + '</p>\
<p>主演:' + mainActor.reduce(function (prev, curv) {
console.log(mainActor)
prev += curv +' '; //加空字符串是为了把名字分开
return prev;
}, '') + '</p>\
<p>编剧' + screenWriter.reduce(function (prev, curv) {
prev += curv +' ';
return prev;
}) + '</p>\
</div>'
// 创建标签没有样式,可以给它加样式
$(htmlStr).appendTo('body')
.css({
position: 'absolute',
left: $(window).outerWidth() /2,
bottom: -100,
width: 400,
marginLeft: -200
})
}
});
}).children()
.eq(0).attr('src', ele.poster)
.next().text(ele.name)
.data()
// 添加成功后,还需要传给它的父级
$Wrapper.append($MovieSection);
})
}
})
} else {
// 非VIP
}
}
});
可以从编辑器看到代码格式形成三角区域,说明已经进入回调地狱: 它不符合六大原则:单一原则(一层层嵌套ajax方法),开闭原则(只能在ajax函数里写,不能在外面写)![]()
总结:回调地狱
1.函数作为参数层层嵌套
2.一个函数作为参数依赖另一个函数执行

浙公网安备 33010602011771号