一、前言
由于js是单线程的,所以异步操作就显得非常重要。而promise能便于我们异步编程。这里只记录promise的主要功能。
二、理由
为什么会出现Promise这种东西呢?
在Promise出现前,一般使用回调函数。而在出现大量串行执行的异步操作时便会出现 “ 回调地狱”
func1((val1)=>{
func2((va2)=>{
func3((val3)=>{
func4((val4)=>{
...
})
})
})
})
这种代码不仅样子不好看、不直观,而且增加了debug难度。
所以需要一种新的异步编程方法,promise应运而生。
三、使用
1.resolve / reject
首先看一个Promise实例:
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
},1000)
//使用setTimeout模仿异步操作
})
使用Promise的要点之一就是 new 一个Promise对象,传入一个形如 (resolve,reject){ } 的函数。
这里resolve的意思是把得到的正确结果处理掉,而reject则是抛出错误结果或者错误。简单地说,你只需要在异步操作后resolve正确结果,或者reject错误就行辽。
但是请注意!只能 resolve 或者 reject 一次,多余的会无视。
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
resolve("p11");
reject("p1111");
})
})
p1.then((val)=>{
console.log(val); // 结果为: p1
})
2.then / catch
看完上一条,你可能会有疑问:“ resolve后怎么自己处理这个值? ”
Promise有一点很巧妙的是,它把异步的执行部分和处理部分分开了。上面传入的 (resolve,reject){ } 是为执行部分,下面介绍的 then / catch 为 处理部分。
var p1 = new Promise((resolve,reject)=>{ //执行部分
setTimeout(()=>{
resolve("p1"); //弹出 p1
})
})
//这里收到 p1
p1.then((value)=>{ //处理部分
console.log(value); // p1
})
你可以假设 resolve / reject 弹出了异步结果,然后 then 会接住这个结果然后执行处理部分的代码。
如果需要截获 reject 的错误则用 catch
var p1 = new Promise((resolve,reject)=>{ //执行部分
setTimeout(()=>{
reject("p1 error"); //弹出 "p1 error"
})
})
p1.then((value)=>{ //处理部分
console.log(value); //这里收不到reject的结果
}).catch((error)=>{
console.log(error); //catch可以收到reject的结果
})
3.promise链式调用
前面的内容你可能觉得并没有解决 “回调地狱” 的问题,而 promise链式调用 其实才是关键。
举个简单栗子:
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
})
})
p1.then((value)=>{
console.log(value);
return "p2";
}).then((value)=>{
console.log(value);
return "p3";
}).then((value)=>{
console.log(value);
})
/*结果:
p1
p2
p3
*/
可以发现,上一个 then 中 return 的结果会在下一个then中获得。这里只是return了字符串,假设return 的是Promise对象呢?
再举个栗子:
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
})
})
p1.then((value)=>{
console.log(value);
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve("p2")},1000);
});
}).then((value)=>{
console.log(value);
return new Promise((resolve,reject)=>{
setTimeout(()=>{resolve("p3")},1000);
});
}).then((value)=>{
console.log(value);
})
/*结果:
p1
p2
p3
*/
只要return Promise , 下一个 then 便会获得resolve的结果。这样大大改善了 “回调地狱” 。
4.all
Promise 提供了 all方法,用于同时运行多个 Promise对象,然后全部运行完后才返回全部结果。
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
})
})
var p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p2");
})
})
p1.then((value)=>{
return value;
})
p2.then((value)=>{
return value;
})
//同时运行 p1和p2
Promise.all([p1,p2]).then((val)=>{
console.log(val); // [ 'p1', 'p2' ]
});
5.race
Promise 还提供了 race 方法,用于同时运行多个 Promise对象,然后返回最先运行完的结果(但另外一个还是会继续运行,只是不返回结果了)
var p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p1");
},2000)
})
var p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("p2");
},1000)
})
p1.then((value)=>{
return value;
})
p2.then((value)=>{
return value;
})
//同时运行
Promise.race([p1,p2]).then((val)=>{
console.log(val); // 'p2'
});
本文深入讲解Promise的基础概念和使用技巧,包括resolve/reject、then/catch、链式调用、all和race方法,帮助读者理解如何利用Promise改善异步编程中的回调地狱问题。
811





