Promise是ES6中新增的语法,主要是解决原来回调地狱,也就是回调函数多层嵌套问题。
现在我有两个json文件,分别用ajax来请求,但是要求先请求data.json的数据,然后再请求data1.json的数据。
javascript"> $.ajax({
url: './data1.json',
dataType: 'json',
success: function (data) {
console.log(data);
}
})
$.ajax({
url: './data.json',
dataType: 'json',
success: function (data) {
console.log(data);
}
})
显然,上面的代码是无法保证请求顺序的,你可以不断的刷新来试一试,总是不一样的顺序。
那么,自然而然就想到了回调函数(callback),让请求data1的ajax方法放在回调函数中,等data.json数据请求完毕后再执行。
javascript"> function callback() {
$.ajax({
url: './data1.json',
dataType: 'json',
success: function (data) {
console.log(data);
}
})
}
$.ajax({
url: './data.json',
dataType: 'json',
success: function (data) {
console.log(data);
callback();
}
})
这样子是可以保证请求顺序的。但是,如果我的需求是请求100个这样的json文件,且要保证顺序,那么我是不是就要在一个回调函数中嵌套另外一个回调函数,再在新的回调函数中再嵌套一个回调函数…
如下图所示,这样就成了回调地狱(callback hell)
为了保证异步函数的执行顺序,不得不使用回调函数嵌套的方法,这样的代码写出来不仅可读性不好,可维护性也很差。试想你愿意修改这样的代码吗?Promise能让我们的代码变得更加优雅。
javascript"> var p2 = new Promise((resolve, reject) => {
$.ajax({
url: './data1.json',
dataType: 'json',
success: function (data) {
resolve(data);
},
error: (err) => {
reject(err);
}
})
});
var p1 = new Promise((resolve, reject) => {
$.ajax({
url: './data.json',
dataType: 'json',
success: (data) => {
resolve(data);
},
error: (err) => {
reject(err);
}
})
});
p1
.then((data) => {
console.log(data);
return p2; //return 一个Promise对象,接收的其实是这个对象的两个形参函数.
}, (err) => {
console.log('请求失败!', err);
})
.then(data => {
console.log(data);
}, err => {
console.log('请求失败!', err);
})
当请求成功时,把数据给到resolve函数,失败时把错误给到reject函数。
然后用Promise的实例方法then实现resolve方法和reject方法。
在p1中return的值,可以是任意的,但是一般都是一个Promise对象,这样才有意义。虽然返回的是一个Promise对象,但是下一个then方法接收的参数为这个返回的Promise对象中的resolve方法和reject方法。
注意,Promise不是异步的,它只是内部封装了一个异步函数而已。
使用Promise时,通常都会把它封装为一个函数。我们把上面的代码改造一下。
javascript"> function ajaxPromise(ajaxUrl) {
return new Promise((resolve, reject) => {
$.ajax({
url: ajaxUrl,
dataType: 'json',
success: (data) => {
resolve(data);
},
error: (err) => {
reject(err);
}
})
})
}
ajaxPromise('./data.json')
.then(data => {
console.log(data);
return ajaxPromise('./data1.json');
}, err => {
console.log('请求失败!', err);
})
.then(data => {
console.log(data);
}, err => {
console.log('请求失败!', err);
})
这样子的代码,相对于回调函数的层层嵌套,是不是很优雅,很漂亮呢?