目录
前言
Promise的基本用法
封装ajax的请求
Promise中常见的误区
Promise并行执行
回调函数可以说是Javascript中异步编程的根基,如果我们使用传统的方法去实现复杂的异步过程,就会很容易形成回调地狱,实现起来非常不优雅而且比较难维护。那么,有没有一种能解决这种问题呢?答案是肯定的。ES2015提供了一种规范,用来解决这种问题,这种规范就叫Promise。
promise接受一个函数,这个函数接受
两个参数,一个是成功的resovle,另一个是失败的reject。
const promise = new Promise(function (resolve, reject) {
resolve("成功");
//reject("失败");
})
promise.then(function (value) {
console.log("resolve", value); //resolve 成功
}, function (error) {
console.log("reject", error);
})
上例中,我们调用promise的then方法,该方法有两个参数,第一个对应的是上面定义的resolve方法,我们可以在里面实现成功时候的方法,第二个对应的是上面定义的reject方法,我们可以在里面实现失败后的方法。需要注意的是,我们定义Promise时传入的两个参数中,只有一种结果,要么是成功,要么是失败。如下图展示:
const promise1 = new Promise(function (resolve, reject) {
resolve("成功");
reject("失败");
})
promise1.then(function (value) {
console.log("resolve", value) // resolve 成功
}, function (error) {
console.log("reject", error); // 不执行
})
const promise2 = new Promise(function (resolve, reject) {
//resolve("成功");
reject("失败");
})
promise2.then(function (value) {
console.log("resolve", value) // 不执行
}, function (error) {
console.log("reject", error); // reject 失败
})
我们可以使用Promise来封装ajax的请求,定义一个方法,该方法返回一个Promise。
function ajax (url) {
return new Promise(function (resolve,reject ) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.onload = function () {
if(this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
}
xhr.send();
})
}
ajax("XXXX").then(function (res) {
console.log(res);
}, function (error) {
console.log(error);
})
使用Promise中有个常见的误区,就是嵌套使用,例如当我们请求3依赖于请求2的结果,而请求2又依赖于请求1......如此,我们可能会这样写:
ajax('api/users').then(function (user1) {
ajax(user1).then(function (user2) {
ajax(user2).then(function (user3) {
ajax(user3).then(function () {
})
})
})
})
这样写是错误的。这时,我们可以利用promise的链式调用,实现扁平化。需要注意的是:
链式调用的使用方法,异常的捕获建议采用catch方式。如下:
ajax('api/users').then(function (value) {
console.log('resolve',value);
return ajax('/error-url');
}).catch(function (error) {
console.log("error",error);
})
var promiseAll = Promise.all([
ajax('请求1'),
ajax('请求2')
])
promiseAll.then(function (values) {
console.log(values); //返回的结果是一个数组,两个请求都成功才返回,其中一个失败则不返回
console.log(values[0]); //请求1结果
console.log(values[1]); //请求2结果
}).catch( function (error) {
console.log(error);
})
最后补充一点,Promise的执行顺序属于微任务,优先于setTimeout的执行。