浅谈JS异步(asychrouous)
一、概念
(1)asychronous 异步
是JS这种单线程语言解决多任务的一种方法,将耗时的任务(io)设定为异步工作,先交给浏览器负责相关功能的线程来实现耗时的部分工作,按顺序放入任务队列中,等待主代码执行完成,而主线程继续下一个任务,不阻塞代码;主线程任务完成后,会收到浏览器的通知,来实现异步任务的其他代码执行
===>事件循环+任务队列
(2)sychronous 同步
任务的执行是一个接着一个执行的,上一个任务执行完成才能继续下一个任务,有多个窗口,进行一个接一个的执行任务
二、异步有序问题
1、回调=====>回调地狱
当我们需要进行有序任务时,最粗暴的方式就是用时间函数嵌套,少个还可以分辨,但若出现上百、上千个事件呢?如果任然使用这种方法,就会形成“回调地狱”,没有办法阅读处时间函数的时间对应的代码是哪一个,不利于后续的维护:
setTimeout(function () {
console.log("a");
setTimeout(function () {
console.log("b");
setTimeout(function () {
console.log("c");
setTimeout(function () {
console.log("d");
}, 1000)
}, 2000)
}, 1000)
}, 1000)
于是乎,我们的先人们捣鼓出了专门处理异步的方法。
2、Promise 构造函数
首先,我们来看一看使用Promise 构造函数与上面的代码有什么不同
new Promise(function (resolve, reject) {
// console.log("a1");
setTimeout(function () {
console.log("a");
resolve();
}, 1000)
}).then(() => {
// return 1;//下一个then被处罚时可以接收返回值 return new Promise(function (resolve, reject) {
// console.log("b1");
setTimeout(function () {
console.log("b");
resolve();
}, 2000)
})
}).then((data) => {
return new Promise(function (resolve, reject) {
// console.log("c1");
setTimeout(function () {
console.log("c",data);
resolve();
},3000)
})
})
我们可以看到,Promise让每一个异步都是平行的了,不再是嵌套关系,语义化非常强,让人一眼可以看出每个事件发生的顺序。
(1)使用Promise要注意状态值:
- pending 已就绪, Promise实例化的同时就已就绪,状态只可改变1次,且不可逆
- resolved/fulfilled 已完成
- rejected 已失败
===>状态改变,then方法会触发onfulfilled,onrejected事件
(2)Promise构造函数
我们分步骤来看,是怎样应用的:
new Promise(function(resolve,reject){});
let fn1;
let fn2;
new Promise(function(resolve,reject){//两个形参,都是回调函数
resolve();
fn1 = resolve;
fn2 = reject;
});
resolve()方法会返回已完成状态,就会触发onfulfilled事件,让then()代码走下去
若要写异步函数,则将第一个异步函数写在Promise里面,之后每一个任务可以使用then()来触发,每个then()只能完成一个任务
p.then((data)=>{//参数为2个事件监听器,第一个是已成功时触发,第二个是以失败时触发
console.log("onfulfilled",data);
},(data)=>{
console.log("onrejected",data);//onrejected 触发且异常,不报错
}) console.log(p);
then :
- 返回值为promise对象,初始状态是pending
- 监听器被触发,监听函数执行完成后,返回值的状态发生改变
- 改变的情况由监听函数的执行返回值决定,而具体情况参照Promise.resolve(返回值)
then(onfulfilled,onrejected)含有两个参数,都是事件监听器(函数),第一个是已成功时触发,第二个是以失败时触发。onrejected 触发且异常时,不报错。
整体的代码就是:
let fn1;
let fn2;
let p = new Promise(function(resolve,reject){//两个形参,都是回调函数
resolve();
//第一个异步函数放在Promise里
fn1 = resolve;
fn2 = reject;
}); p.then((data)=>{//参数为2个事件监听器,第一个是已成功时触发,第二个是以失败时触发
console.log("onfulfilled",data); },(data)=>{
console.log("onrejected",data);//onrejected 触发且异常,不报错
}) console.log(p);
(3)all(),race()
在Promise中有两个好用的方法,就是 all(),race()
- all()方法:在所有异步代码都跑了后,同时输出结果,但结果显示顺序根据异步事件结束的先后来的
let p1 = new Promise(function (resolve, reject) {
console.log("a开始了"); setTimeout(function () {
console.log("a");
resolve();
}, 4000)
})
let p2 = new Promise(function (resolve, reject) {
console.log("b开始了");
setTimeout(function () {
console.log("b");
resolve();
}, 3500)
})
let p3 = new Promise(function (resolve, reject) {
console.log("c开始了");
setTimeout(function () {
console.log("c");
resolve();
}, 5000)
}) let pp = Promise.all([p1,p2,p3]);
pp.then(()=>{
console.log("all"); })
- race()方法:赛跑,谁先结束谁先输出
let p1 = new Promise(function (resolve, reject) {
console.log("a开始了"); setTimeout(function () {
console.log("a");
resolve();
}, 4000)
})
let p2 = new Promise(function (resolve, reject) {
console.log("b开始了");
setTimeout(function () {
console.log("b");
resolve();
}, 3500)
})
let p3 = new Promise(function (resolve, reject) {
console.log("c开始了");
setTimeout(function () {
console.log("c");
resolve();
}, 5000)
}) // let pp = Promise.all([p1,p2,p3]);
// pp.then(()=>{
// console.log("all"); // }) pp = Promise.race([p1,p2,p3]);
pp.then(()=>{
console.log("race"); })
b时间最短,因此是b获胜
all、race 都生成promise对象,但是状态的变化情况不一样
(4)返回值 return
Promise.value 通过resolve传递的参数
Promise.reslove(value)方法,返回一个以给定值解析后的Promise对象
value有三种情况:
- 普通值:除了promise对象,和thenable对象的所有值,生成一个已完成的promise对象并且PromiseValue的值就是传入的value
- promise对象,直接返回该value
- thenable对象,参照new Promise 生成的promise对象,其中then方法就好比new Promise(cb)中的cb
在then(data)中,data就是value的值,我们回到开头的那段代码:
new Promise(function (resolve, reject) {
// console.log("a1");
setTimeout(function () {
console.log("a");
resolve();
}, 1000)
}).then(() => {
// return 1;//下一个then被处罚时可以接收返回值 return new Promise(function (resolve, reject) {
// console.log("b1");
setTimeout(function () {
console.log("b");
resolve();
}, 2000)
})
}).then((data) => {
return new Promise(function (resolve, reject) {
// console.log("c1");
setTimeout(function () {
console.log("c",data);
resolve();
},3000)
})
})
then(() => {
// return 1;//下一个then被处罚时可以接收返回值,大家可以自己去试一试。
最新文章
- springMVC之servlet-config.xml配置
- Zepto源码注释
- JAVA 匿名对象
- JAVA实现word doc docx pdf excel的在线浏览 - 仿百度文库 源码
- GCD 之 同步 异步 并发
- 获取元素到body/html的距离函数
- 关于KVO导读
- unity爬坑记录
- linux命令df中df -h和df -i
- C# 之 GUID格式化
- Apache kylin的基础环境
- jquery计算时间差(天、时、分、秒)并使用定时器实时获取
- mac上命令行解压rar
- MySql获取两个日期间的时间差
- rnn-nlp-单词预测
- 尚硅谷springboot学习20-web开发简介
- Qt 立体水晶按键实现
- 径向基(RBF)神经网络python实现
- Paxos Made Simple【翻译】
- eclipse Java compiler level does not match the version of the installed Java project facet.
热门文章
- tensorflow学习笔记——ResNet
- kafka性能测试代码
- Elasticsearch慢查询故障诊断
- Java第一次创建对象速度比之后慢的原因
- 浅谈Redis的基本原理和数据类型结构的特性和应用开发场景
- 洛谷$P4045\ [JSOI2009]$密码 $dp$+$AC$自动机
- linux 双Redis + keepalived 主从复制+宕机自主切换
- 使用Selenium对网页元素进行定位的诸种方法
- 1065 单身狗 (25分)C语言
- Spring Cloud Stream消息驱动@SendTo和消息降级