什么是回调地狱
前端的ajax和jsonp内部充斥着大量的异步,为了能够拿到异步的数据,使用了大量的回调函数,来获取将来异步执行成功之后的数据
//d1.php
<?php
echo "d1的数据";
?>
//d2.php
<?php
echo "d2的数据";
?>
//d3.php
<?php
echo "d3的数据";
?>
document.onclick = function(){
//1.回调地域
ajax({
url:"http://localhost/promise/d1.php",
success:function(res1){
console.log(res1);
ajax({
url:"http://localhost/promise/d2.php",
success:function(res2){
console.log(res2);
ajax({
url:"http://localhost/promise/d3.php",
success:function(res3){
console.log(res3);
console.log(res1, res2, res3);
}
})
}
})
}
})
}
解决回调地狱的方法:
Promise:
Promise 是回调地狱的解决方案之一
我们使用 Promise 的语法来解决回调地狱的问题
使代码拥有可读写和可维护性
原理:
Promise承诺,异步
正在执行时…异步过程
成功
失败
成功或失败虽然是将来才会发生,但是在承诺开始的时刻,就需要提前预置
发生了成功,必然不会执行失败
发生了失败,必然不会执行成功
语法:(语言的法律法规,固定!!!!!)
Promise是一个构造函数
new的同时立即传参,参数是回调函数,回调函数身上可以接受两个参数,分别是:resolve(success,成功),reject(error,失败)
var p = new Promise(function(a,b){
// 正在执行…
// 此处放置异步的程序
// a就是在then中的第一个回调函数,表示成功要做的事情
// b就是在catch中的第一个回调函数,表示失败要做的事情
});
p.then(function(){
// 成功的预置函数
});
p.catch(function(){
// 失败的预置函数
});
1.promise解决回调地域-没有保存变量版
document.onclick = function(){
var p1 = new Promise(function(success,error){
ajax({
url:"http://localhost/promise/d1.php",
success:function(res1){
success(res1);
}
})
}).then(function(r1){
console.log(r1);
return new Promise(function(success,error){
ajax({
url:"http://localhost/promise/d2.php",
success:function(res2){
success(res2);
}
})
});
}).then(function(r2){
console.log(r2);
return new Promise(function(success,error){
ajax({
url:"http://localhost/promise/d3.php",
success:function(res3){
success(res3);
}
})
})
}).then(function(r3){
console.log(r3);
})
2.promise解决回调地域-保存变量版
var p1 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d1.php",
success:function(res1){
resolve(res1);
}
})
})
var p2 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d2.php",
success:function(res2){
resolve(res2);
}
})
})
var p3 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d3.php",
success:function(res3){
resolve(res3);
}
})
})
p1.then(function(r1){
console.log(r1);
return p2;
}).then(function(r2){
console.log(r2);
return p3;
}).then(function(r3){
console.log(r3);
})
promise的批处理
var p1 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d1.php",
success:function(res1){
resolve(res1);
}
})
})
var p2 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d2.php",
success:function(res2){
resolve(res2);
}
})
})
var p3 = new Promise(function(resolve){
ajax({
url:"http://localhost/promise/d3.php",
success:function(res3){
resolve(res3);
}
})
})
// 批处理-all:全部成功,即为成功(拿到的数据是所有数据),只要有一个失败,即为失败
// Promise.all([p1,p2,p3]).then(function(ultimate){
// console.log(ultimate);
// })
// 批处理-race:得到最先结束的状态,不管是成功(当前成功的数据)还是失败
Promise.race([p1,p2,p3]).then(function(ultimate){
console.log(ultimate);
})
}
总结:promise就是一种固定语法,固定写法,固定传输
所有的原理都在promise的内部被封装
封装的ajax-promise
function ajax(ops){
ops.type = ops.type || "get";
ops.data = ops.data || {};
var str = "";
for(var key in ops.data){
str += `${key}=${ops.data[key]}&`;
}
if(ops.type=="get"){
let t = new Date().getTime();
ops.url = ops.url + "?" + str + "__qft="+ t;
}
var xhr = new XMLHttpRequest();
xhr.open(ops.type, ops.url);
if(ops.type == "get"){
xhr.send();
}else{
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(ops.data);
}
return new Promise(function(resolve,reject){
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
resolve(xhr.responseText);
}else if(xhr.readyState === 4 && xhr.status !== 200){
reject("当前请求失败了,失败的原因是:" + xhr.status);
}
}
})
}
在Promise的基础上,再使用async/await
async / await 是 ES7( ES2016 ) 的新增语法
是回调地狱的终极解决方案
我们就是用 async / await 语法把 异步代码写的看起来像同步代码
async function fn(){
var p1 = await ajax({
url:"http://localhost/promise/d1.php"
});
var p2 = await ajax({
url:"http://localhost/promise/d2.php"
});
var p3 = await ajax({
url:"http://localhost/promise/d3.php"
});
console.log(p1, p2, p3);
console.log(abc);
}
document.onclick = function(){
fn();
}
总结:promise是用来处理所有的异步的回调地狱,不止是ajax,任何一个异步,只是是回调地狱的调用形式,就可以使用promise改造