通过代码实例带你了解Promise
本篇文章通过多段代码实例带大家了解 Promise 的基础用法,以及更进一步掌握 Promise 异步存取的思想。
之前一直有听说 Promise 的威名,但是总觉得是个较为深奥的东西,有点畏难而没能真正地去了解。最近看了李立超老师在B站传的 Node.js 的视频,感觉讲的很清晰,自己在这做进一步的梳理。
先来看一个问题
我们都知道 JavaScript 是单线程运行的,所以如果遇到一个数据需要过段时间才能获取到的情况,就会形成阻塞导致后面的代码也无法执行,而这相当致命,比如下面代码
function sum(a, b) {
const begin = Date.now();
while(Date.now() - begin < 10000) {
}
return a+b;
}
console.log(sum(1,2));
console.log("1");
中间的 while 语句经历了10秒的循环,最终才分别打印出了 3 和 1
然而我们希望的是允许3在10秒后再打印出来,但是1得先打印出来
这里我们就用到了setTimeout
,修改代码如下
function sum(a, b) {
setTimeout(() => {
return a+b;
},10000)
}
console.log(sum(1,2));
console.log("1");
运行一下可以看到1确实瞬间被打印出来了,但是本该打印3的位置是undefined
原因在于此时的console.log
同样没有等待setTimeout
走完,无法接收到10秒后的数据
所以为了能够接收到这个10秒后的数据,我们可以采用回调函数的方式
function sum(a, b, callback) {
setTimeout(() =>{
callback(a+b);
}, 10000)
}
sum(1,2,(result) => {
console.log(result);
});
console.log("1");
传入了一个能够接收 a+b 为参数的回调函数 (result) => {console.log(result);}
所以在10秒后会执行这个回调函数,进行打印,结果如下
这样我们就初步解决了这个问题,一个需要延时获取的数据在其他代码先执行后再被获取。
然而 Promise 还没出现,这就涉及了另一个需要改进的地方
回调地狱
这是个乍一听很唬人的称呼,实际上就是多层回调函数的嵌套导致的不利于阅读和调试的情况。
比如此时我们想要多次调用这个sum函数,要在得到1+2的结果后,再获得 1+2+3,1+2+3+4 这些结果
所以我们得在sum传入的回调函数里再多次调用sum进行嵌套,如下
sum(1,2,(result) => {
sum(result, 3, (result) => {
sum(result, 4, (result) => {
console.log(result);
})
})
});
这种类似金字塔的结构可读性差且不好调试,被称作回调地狱。
所以此时终于到了Promise出场的时候,它的出现解决了回调地狱的问题。
Promise 是什么
在使用Promise解决回调地狱的问题前,先来大致地了解一下什么是Promise。
目前我对它的判断是,Promise 是一个用于存取异步数据的对象。
首先来看一下空的 Promise 打印出来会是什么
const promise = new Promise(()=>{});
其中最关键的就是 PromiseState 和 PromiseResult 两个值,之后会详细展开,这里只要知道Promise中有着这两个属性即可。
接着来看一下 promise 存数据的过程,最关键的就是要知道有 resolve 和 reject,比如下面代码
const promise = new Promise((resolve, reject) => {
const flag = true;
if (flag) {
resolve("resolve datas");
} else {
reject("reject data");
}
})
此时flag为true,所以执行的是resolve的存储,得到的结果如下
而当我们把flag改为false,执行reject的存储时,得到的结果如下
现在是解释上面两个属性的时候了,
- 当 promise 没有存储数据时,PromiseState 的值为 pending,PromiseResult的值为 undefined
- 当 promise 使用 resolve 存储数据时,PromiseState 的值为 pending,PromiseResult的值为 相应存储值
- 当 promise 使用 reject 存储数据时,PromiseState 的值为 rejected,PromiseResult的值为相应存储值
既然存有两种类型,读自然也要分两种
当我们读取promise中的数据时,我们需要使用如下的结构
promise.then(result => {
console.log(result);
}, reason => {
console.log(reason);
})
如果数据存在resolve中,result会返回结果,如果存在reject中,reason会返回结果。
使用Promise解决回调地狱
在初步了解了Promise后,会发现目前Promise能做的事,使用回调函数也能完成。
所以最主要的还是Promise解决了回调地狱,比如之前的问题,可以写成这种形式
function sum(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a+b);
}, 1000);
})
}
sum(1,2)
.then(result => sum(result,3))
.then(result => sum(result,4))
.then(result => {
console.log(result);
})
promise 通过then方法进行读取后,是个新的Promise对象,比如我们可以打印一下
function sum(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a+b);
}, 1000);
})
}
console.log(sum(1,2)
.then(result => sum(result,3)))
所以这也就给了我们能多次调用then方法的基础。
而这也就解决了回调地狱的问题。
小结
Promise 是一个可以存取异步数据的对象,通过resolve
和reject
来存储数据,可以通过then
来读取数据
至于其他的.catch
.finally
.race
.any
.all
这些方法就不再多作赘述,详细的见文档
【推荐学习:javascript高级教程】
以上就是通过代码实例带你了解Promise的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341