手把手寫: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

css文件:html

* {
		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.一個函數做爲參數依賴另外一個函數執行
相關文章
相關標籤/搜索