这是我参与8月更文挑战的第17天,活动详情查看8月更文挑战
前言
我们应该踏踏实实地把 Promise 是什么,它存在的意义是什么,它为什么这样设计,搞明白以后,我们再去学更深的,比如 Promise 的原理,或者从应用层面上,我们应该掌握的 Promise 的使用技巧。今天我们就来聊聊 Promise 的存在意义。可以看下下面两个问题,你是否知道:
- 为什么 Promise 的构造函数是同步执行,包括里面的执行器?
- 为什么 Promise.then 这样的东西一定是异步的,为什么不能是同步的?
使用 AJAX 实现异步程序
假设有 data.json,存储一些数据
[
{
"id": 1,
"name": "zhangsan"
},
{
"id": 2,
"name": "lisi"
},
{
"id": 3,
"name": "wangwu"
}
]
index.js 去通过 ajax 获取到数据,并做相关处理:
$.ajax({
url: 'http://localhost:3000/data.json',
success(data) {
console.log(getNames(data));
}
});
console.log('追梦玩家');
function getNames(data) {
return data.map(function(item) {
return item.name;
})
}
上面代码输出结果,因为 ajax 是异步的,所以先打印 "追梦玩家"。
逻辑从 AJAX 内部抽离出来
在上面的代码的基础上,进行改写,实现 console.log(getNames(data)); 从 AJAX 内部抽离出来
我们先来尝试一下:
var data = $.ajax({
url: 'http://localhost:3000/data.json',
async: false
});
console.log(getNames(data.responseJSON));
console.log('追梦玩家');
function getNames(data) {
return data.map(function(item) {
return item.name;
})
}
上面的代码,通过设置 async: false,让代码变成同步关系,我们就成功的把这个逻辑分离的事情做完呢?实际上没有。
它们俩原本是异步程序,但是由于你设置了 async: false,形成了阻塞,说白了,就是上面那个 ajax 程序,跟下面的每一个语句都形成了同步关系。
这显然是不符合我们的需求的,虽然说我们已经将 getNames 这个逻辑,从 AJAX 内部抽离出来,但是实际上让 console.log('追梦玩家'); 被 ajax 程序给阻塞掉,形成一个同步的关系。那我们使用最原始的 ajax,解决不了这个问题,这才有了 Promise 的诞生。
Promise 异步问题同步化解决方案
我们使用 Promise,来解决使用 ajax,设置 async: false,后续程序全部阻塞掉的这个问题。
我们改造下代码
// 同步
const p = new Promise((resolve, reject) => {
$.ajax({
url: 'http://localhost:3000/data.json',
success(data) {
resolve(data);
}
});
})
// 异步
p.then((res) => {
console.log(getNames(res));
})
console.log('追梦玩家');
function getNames(data) {
return data.map(function(item) {
return item.name;
})
}
执行 Promise 构造函数,是同步的,但是里面的代码,异步请求数据,等成功获取到数据,resolve 之后,p.then 才会去执行。
其实 p.then 不能去阻塞下面程序的运行,也就是说 p.then 这个东西,跟下面的程序代码,一定是要是异步的关系,这样的话,才能解决我上面的问题。
所以现在我们来看看,Promise 的存在意义是用来解决回调地狱的吗?其实它只是顺便给你解决了回调地狱的问题。
Promise 的存在意义,其实是异步问题同步化解决方案,这个要怎么理解呢?
AJAX 是异步的,通过包裹了 Promise,可以通过 Promise.then 来获取异步程序的结果,并且不阻塞 Promise 以外的程序,跟 Promise 不相关的任何程序,保持异步关系。
现在解决回调地狱,真的是用 Promise 是最好的解决方案吗?最佳方式是使用 async/await 的方式,它可以让我们以同步代码的书写方式去写异步代码,这是es6的语法。
参考
文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你或者喜欢,欢迎点赞和关注。