Promise是什么鬼?
用vue的时候ajax是用的axios封装,一直不知道为何有.then这样简洁明了的写法,
方便的背后一直没有去深究其理,今天就来看看Promise
总所周知js是单线程,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现,如经典的ajax,是这么玩的:
request.onreadystatechange = function () {
if (request.readyState === 4) {
if (request.status === 200) {
return success(request.responseText);
} else {
return fail(request.status);
}
}
}
用了异步是这样的:
ajax.then(callback(success)).catch(callback(error))
so:看看怎么封装Promise:
在我看来Promise就是个语法糖,按照特定的写法进行解析而已:
引用下廖雪峰官网的一句总结:
来自廖雪峰官网
玩个简单的比较傻逼的 promise game,看看Promise是怎么玩的,直接上代码:
<script>
function add(count) {
return new Promise(function (res, rej) {
count++;
console.log(`current count: ${count}`);
if (count < 5) { //满足条件的时候都执行res
setTimeout(() => {
res(count);
}, 500);
} else {
rej("promise game over")
}
})
}
p = new Promise((resolve, reject) => { //p为一个promise实例,没有做条件判断,只会执行resolve
let count = 0;
console.log('start game:' + count)
resolve(count);
})
p.then(add)
.then(add)
.then(add)
.then(add)
.then(add)
.then(add)
.then(add)
.then(add)
.then(add)
.catch((error) => {
console.log('hahaha'+ error)
})
</script>
结果:
start game:0
test.html:5 current count: 1
test.html:5 current count: 2
test.html:5 current count: 3
test.html:5 current count: 4
test.html:5 current count: 5
test.html:5 current count: 6
test.html:32 hahahapromise game overcatch 中执行rejcet回调
所以: Promise对象就是参数中的resolve和reject两个参数分别放到then和catch中执行。而且和
两个参数的名字没关系,参数名字可以写成res,rej都可以
-
除了串行执行若干异步任务外,Promise还可以并行执行异步任务。
p1 = new Promise(function(resolve, reject){
let time = 2000;
setTimeout(() => {
resolve("p1返回了" + time)
}, time);
})
p2 = new Promise(function(resolve, reject){
let time = 3000;
setTimeout(() => {
resolve("p2返回了" + time)
}, time);
})
let startTime = Date.parse(new Date());
Promise.all([p1, p2]).then((result)=>{
console.log(result)
let useTime = (Date.parse(new Date()) - startTime)/1000;
console.log("use:" + useTime + 's')
})
会在两个promise都执行完后才一起返回结果,应用场景是在同时两个异步请求完成需要计算的时候,代码运行结果:
["p1返回了2000", "p2返回了3000"]
use:3s
3s后数组形式返回两个异步函数的结果
-
有些时候,多个异步任务是为了容错。比如,同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现:
p1 = new Promise(function(resolve, reject){
let time = 2000;
setTimeout(() => {
resolve("p1返回了" + time)
}, time);
})
p2 = new Promise(function(resolve, reject){
let time = 3000;
setTimeout(() => {
resolve("p2返回了" + time)
}, time);
})
let startTime = Date.parse(new Date());
Promise.race([p1, p2]).then((result)=>{
console.log(result)
let useTime = (Date.parse(new Date()) - startTime)/1000;
console.log("use:" + useTime + 's')
})
会返回先执行的一个函数,忽略掉剩下的函数,代码运行结果:
p1返回了2000
use:2s
2s后返回p1的结果,忽略了p2
写在结尾的:玩够了回调地狱,玩玩promise也不错