一.Promise产生的背景
前言:JavaScript是单线程语言,所以在执行耗时较大的任务时会导致页面阻塞。为了解决页面阻塞,异步执行被提了出来(异步被放在任务队列中,当所有同步执行完毕再去执行异步,而任务队列的异步有不是依次执行,谁耗时少就先执行谁)。异步带来一个执行顺序的问题,要想按照顺序依次执行,怎么办呢?最传统的方法是使用回调函数,也就是callback,但是callback是嵌套型的,就产生了很多弊端,比如:代码耦合性强,阅读起来不直观。后来ES6新增了一个Promise,Promise的到来在一定程度上改进了代码的可读性,Promise将callback的嵌套结构改为了链式结构。但链式结构的语义还是不够简单明了,那么async/await就应运而生,sync/await可以把异步代码写得像同步代码那样直观,需要注意的是async/await是基于Promise实现的,本质上还是Promise,属于Promise的语法糖。下面我将通过不同的方法来实现一个例子。需求:一共有三个方法一个输入,三个方法分别为getAgeFun(),getNameFun(),getAdressFun(),输入为input。通过这个input得到一个age,通过age得到一个name,通过name得到adress。
1.首先我们用同步的方法来实现:打印出来的都是undefined。
function getAgeFun(input) {
var Age;
setTimeout(function () {
Age = input * 2;
}, 1000)
return Age;
}
function getNameFun(Age) {
var name
setTimeout(function () {
name = "yyl" + Age
}, 1000)
return name;
}
function getAdressFun(name) {
var adress
setTimeout(function () {
adress = name + "YuZhou";
}, 1000)
return adress;
}
//由于是异步,所以Age,name,adress打印出来的都是undefined
var Age = getAgeFun(10);
console.log(Age);
var name = getNameFun(Age);
console.log(name)
var adress = getAdressFun(name);
console.log(adress);
2.使用Promise实现:每隔一秒便打印出来一个值,分别为20,yyl-20,yyl-20-YuZhou
function getAgeFun(input) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var age = input * 2;
resolve(age)
}, 1000)
})
}
function getNameFun(age) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var name = "yyl-" + age
resolve(name)
}, 1000)
})
}
function getAdressFun(name) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var adress = name + "-YuZhou";
resolve(adress);
}, 1000)
})
}
function test() {
getAgeFun(10).then(function (Age) {
console.log(Age);
return getNameFun(Age);
}).then(function (name) {
console.log(name)
return getAdressFun(name);
}).then(function (adress) {
console.log(adress)
})
}
test()
3.使用async/await实现:每隔一秒便打印出来一个值,分别为20,yyl-20,yyl-20-YuZhou
function getAgeFun(input) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var age = input * 2;
resolve(age)
}, 1000)
})
}
function getNameFun(age) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var name = "yyl-" + age
resolve(name)
}, 1000)
})
}
function getAdressFun(name) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
var adress = name + "-YuZhou";
resolve(adress);
}, 1000)
})
}
async function test() {
var age = await getAgeFun(10);
console.log(age);
var name = await getNameFun(age);
console.log(name);
var adress = await getAdressFun(name);
console.log(adress);
}
test()
二.Promise的使用
Promise主要有then、resolve、reject、catch、all和race方法,下面我将逐一讲解。
1.首先resolve代表成功后抛出的结果,then则去处理这种结果,reject代表失败后抛出的结果,catch去处理这种结果。如果随机数小于5,那么该程序就会报错。
var P = new Promise(function (resolve, reject) {
setTimeout(function () {
//parseInt()丢弃小数部分,保留整数部分;Math.ceil()向上取整;Math.floor()向下取整;Math.round()四舍五入;parseInt()与Math.floor()的区别:parseInt()中的参数可以取string类型的,比如parseInt("5.9ss")的结果为5,而Math.floor()的结果是NaN
var randomNum = parseInt(Math.random() * 10);
if (randomNum < 5) {
resolve(randomNum)
}
else {
reject(randomNum)
}
}, 0)
})
P.then(function (res) {
console.log(res)
})
P.catch(function (res) {
console.log(res)
})
2.all方法可以用在多个异步处理中,比如遍历一个数组,对该数组中的各个元素进行异步处理,并且要求返回值的顺序与该数组的顺序一致。
arr = ["a", "b", "c", "d", "e"]
// // map可以return,forEach不可以,所以这里必须要写map,map和forEach里面的参数第一个都是value,第二个是index,第三个是数组本身。jquery里的each和map方法,同样的map可以return,each不可以return,map的参数第一个是value,第二个是index,each的参数第一个是index,第二个是value
var promise = arr.map(function (value,index) {
return new Promise(function (resolve, reject) {
setTimeout(function(){
resolve(value)
//时间是随机的,所以若不是要Promise返回值的顺序将是乱的
},Math.random()*1000)
})
})
//all里面的参数promise是一个数组
Promise.all(promise).then(function (res) {
console.log(res)
//这里写map和forEach都行
res.forEach(function(val){
console.log(val)
})
})
3.race是指返回所有异步中最快的那一个,比如下面这个代码打印的就是个b。
function test1() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("a")
}, 2000)
})
}
function test2() {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("b")
}, 1000)
})
}
Promise.race([test1(), test2()]).then(function (res) {
console.log(res);
})