promise的异步操作
先看一段代码,思考执行的顺序是什么呢?
console.log(1)
setTimeout(function() {
console.log(2);
}, 1000)
console.log(3)
// 打印的结果依次是1 3 2
1.众所周知,javascript是一个单线程的,代码理应是从上往下,并且从左往右开始执行的,那么为什么会出现上述不符合常理的答案?
我们可以设想一下,如果javascript(以下简称js)必须按照单线程的规则进行执行的话,像这样遇到定时器的话必须等到定时器执行完才可以继续执行下面的代码。这就会使页面的显示遇到这种由于等待资源的获取而无法快速的获取页面信息的问题。会大大的降低浏览器的使用。为此出现了同步与异步概念。
简单的来说,大方向还是按照单线程的执行方式,但是遇到需要获取资源不立即显示到页面的一些任务时会把他们统一“丢”到一个“小黑屋”,等到页面上的所有同步的任务执行完成后,再问“小黑屋”中的异步任务获取成功了没有,获取成功的话即可运行。
2.我们又开始想了,遇到这种情况会把我们在js中写的代码的顺序给搞乱了,例如例子里面,这种情况怎么处置呢?
为了解决这类问题我们使用了promise,它主要用来解决异步深层嵌套的问题,在内部提供了简洁的API 使得异步操作更加容易。我们先抛开之前的疑问,先来认识一下今天的主角——promise
首先便是他的使用了!话不多说,上代码!
/* 1.我们使用new来构建一个Promise Promise的构造函数接收一个参数,是函数,并且传入两个参数:
resolve,reject, 分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数 */
new Promise(function(resolve, reject){
consolo.log(1)
//2. 这里用于实现异步任务 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
resolve('hello'); //3. 正常情况
}else{
reject('出错了'); //4. 异常情况
}
}, 1000);
});
// 5 Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数
// 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了
p.then(function(data){
console.log(data) //返回的是正常情况的resolve里面的值
})
.catch(function(data){
console.log(data) //返回的是异常情况的reject里面的值
})
.finally(function(){
console.log('finished') //无论成功与否都会执行
});
//我们可以测试一下打印的结果你会发现,当页面刷新时1是立马打印出来的。
//由此我们可以得知在实例对象promise中只要不进行异步的调用其内部的还是按照同步进行编译。
通过刚才的代码片段我们大概了解到了promise的代码运行顺序,我们结合上文的知识进行异步代码的巩固。
function foo() {
return new Promise(function(resolve, reject){
console.log(1)
setTimeout(function(){
console.log(2)
}, 100);
})
}
console.log(3)
foo()
console.log(4)
setTimeout(function(){
console.log(5)
}, 0);
console.log(6)
// 打印的的结果以此为3 1 4 6 5 2
以上便是promise的基本用法了。怎么样通过promise解决最开始的疑惑呢?
上文已经提到promise实际是一个实例对象,因此可以使用.then、.catch等实例方法。我们设想,如果在第一个then中打印出来我们想要的结果之后返回我们想要调用的第二个promise实例对象可以吗? 答案当然是可以的,正是因为如此我们才可以解决上述问题,只有等前面的请求完成后,才会使用then这个实例方法,在从该实例方法中继续进行下一个异步任务。就像链子一样把他们串联在了一起,这样可以解决回调地狱的问题(即异步任务嵌套异步任务,呈现出了漏斗的代码)。代码实例如下:
//结合ajax调用接口来演示promise的用法
function queryData(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
// 处理正常的情况
resolve(xhr.responseText);
} else {
// 处理异常情况
reject('服务器错误');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
queryData('http://127.0.0.1:3000/data')
.then((data) => {
console.log(data);
return queryData('http://127.0.0.1:3000/data1')
}).then((data) => {
console.log(data);
return queryData('http://127.0.0.1:3000/data2')
})
.then((data) => {
console.log(data);
})
以上只是本人今天学习的皮毛,想要记录下来学习的经历,如有错误,务必指正,不胜感激,小白不建议阅读,还是多去git hub等大型网站阅读前端巨人的文章。
本文地址:https://blog.csdn.net/weixin_52889573/article/details/110203061
下一篇: 斐波那契数列(Java)