一、前言概述
在前端开发中,相信很多读者都使用过AJAX,这种比较???? 逼的异步处理方式,确实在一定程度上方便和简化了我们的某些需求,但有时候也会遇到在一个操作中,会需要多个异步请求的情况,在以往的处理中,比如笔者就曾做过2个及多个AJAX层层嵌套着处理的方式,这种方式,在当时看上去也可以满足一般的需求,但看着别扭,总觉得哪里不爽;
$.ajax({
cache: false,
type: 'POST',
url: url1,
dataType: 'json',
success: function (data) {
$.ajax({
cache: false,
type: 'POST',
url:url2,
data: { para: list},
dataType: 'json',
success: function(result) {
......
}
})
}
})
复制代码
如上,魔鬼嵌套;
很快,随着ES6的发布,Promise横空出世,之前多个AJAX多层嵌套的处理方式,看上去显得那么的low,如此的恶劣不堪,反观Promise,高端大气上档次-------哈哈,是不是有点喜新厌旧的嫌疑啊------瞬间,让我喜欢上了,有点一见钟情的赶脚????
整个就是一大方优雅的典范啊:
readFile(filename).then(function (data) {
return data;
}).then(function (data) {
return readFile(data);
}).then(function (data) {
console.log(data);
}).catch(function(err){
......
});
复制代码
二、原理浅析
-
Promise 名如其实,Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做,例如网络请求、读取本地文件等;
在这个过程中,Promise会经历三个状态:
- Pending Promise对象实例创建时候的初始状态
- Fulfilled 可以理解为成功的状态
- Rejected 可以理解为失败的状态
then 方法就是用来指定Promise 对象的状态改变时确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)
- 示例分析:
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
if(Math.random()>0.5)
resolve('This is resolve!');
else
reject('This is reject!');
}, 1000);
});
promise.then(Fulfilled,Rejected)
复制代码
- 构造一个Promise实例需要给Promise构造函数传入一个函数。
- 传入的函数需要有两个形参,两个形参都是function类型的参数。
- 第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作
- 第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作
三、小试牛刀
经过一些时间的学习和摸索,笔者在ES6自带的Promise的基础上,实现了对其all、race、resolve、reject的功能模拟;
- Promise.all
- 参数:接受一个数组,数组内都是Promise实例。
- 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中所有的实例都处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
- 代码如下
Promise.all = function(promises){
return new Promise(function(resolve,reject){
let done = gen(promises.length,resolve);
for(let i=0;i<promises.length;i++){
promises[i].then(function(data){
done(i,data);
},reject);
}
});
}
复制代码
- Promise.race
- 参数:接受一个数组,数组内都是Promise实例
- 返回值:返回一个Promise实例,这个Promise实例的状态转移取决于参数的Promise实例的状态变化。当参数中任何一个实例处于resolve状态时,返回的Promise实例会变为resolve状态。如果参数中任意一个实例处于reject状态,返回的Promise实例变为reject状态。
- 代码如下:
Promise.race = function(promises){
return new Promise(function(resolve,reject){
for(let i=0;i<promises.length;i++){
promises[i].then(resolve,reject);
}
});
}
复制代码
- Promise.resolve
- 该方法返回一个Promise实例,这个实例处于resolve状态。 会根据传递的参数不同而有不同的功能:
- 当参数是值(对象、数组、字符串等)类型的:作为resolve传递出去的值;
- 当参数是Promise实例:则原封不动返回;
- 代码如下:
//返回一个立刻成功的promise
//但该方法,需要传入一个promise,但你只有一个普通的值,你就可以通过这个方法
//把这个普通的值(string number object)转成一个promise对象
Promise.resolve = function(value){
return new Promise(function(resolve){
resolve(value);
});
}
复制代码
- Promise.reject
- 该方法返回一个Promise实例,这个实例处于reject状态。
- 参数一般就是抛出的错误信息。
- 代码如下:
//返回一个立刻失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
});
}
复制代码
四、小结
以上就是在下对前端经常遇到的异步处理方式的前认与后知;本人自知才疏学浅,如果有一些理解的有失偏颇之处,欢迎各位随时拍砖与指正~!
当然,如果对您还有点作用的话,还望您评论鼓励,以资我继续前行,小可不胜感激~!