浅谈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被处罚时可以接收返回值,大家可以自己去试一试。
浅谈JS异步(asychrouous)的更多相关文章
- 浅谈JS异步轮询和单线程机制
单线程特点执行异步操作 js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步 ...
- 浅谈js异步
大家都知道,js是一个单线程的语言(只有一个线程来执行js函数),所以如果某一个函数执行任务耗时比较长的话,就会造成阻塞,使得后续任务一直处于等待状态. 一.阻塞示例 function f1(){ ; ...
- 浅谈JS之AJAX
0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 浅谈 js 正则字面量 与 new RegExp 执行效率
原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...
- 浅谈 js 字符串之神奇的转义
原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...
- 浅谈 js 正则之 test 方法
原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...
- 浅谈 js 数字格式类型
原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...
- 浅谈 js 语句块与标签
原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...
随机推荐
- ansible核心模块playbook介绍
ansible的playbook采用yaml语法,它简单地实现了json格式的事件描述.yaml之于json就像markdown之于html一样,极度简化了json的书写.在学习ansible pla ...
- 第二阶段:1.流程图:10.visio绘制泳道图
选择跨智能 同时水平 设置好泳道图标题以及泳道名字 泳道位置可以拖拽更换 左侧有一些基本的形状 包括分隔符等等 添加分隔符并填上分隔符上面的阶段名称 左边选择形状界面 然后拖拽使用 同时可以用连接线链 ...
- 「洛谷P2891」[USACO07OPEN]吃饭Dining 解题报告
P2891 [USACO07OPEN]吃饭Dining 题目描述 Cows are such finicky eaters. Each cow has a preference for certain ...
- Groovy重载操作符
重载一时爽,一直重载一直爽. 最近在读<Groovy in action>一本书重新复习了Groovy的一些语法特性,迷恋上这个重载操作符的功能,坚持爽的不要要的.分享一个Demo. 由于 ...
- 【转】7本免费的Java电子书和教程
本文由 ImportNew - 唐小娟 翻译自 Javapapers.如需转载本文,请先参见文章末尾处的转载要求. 1. Thinking in Java (Third Edition) 本书的作者是 ...
- .Net Core Web Api实践(三).net core+Redis+docker实现Session共享
前言:上篇文章介绍了.net core+Redis+IIS+nginx实现Session共享,本来打算直接说明后续填坑过程,但毕竟好多坑是用docker部署后出现的,原计划简单提一下.net core ...
- mysql中emoji表情存储
mysql中emoji表情存储 背景 在mysql 5.7.19,创建的数据库默认选择的编码是utf8 -- UTF-8 Unicode,因此字段默认的编码为utf-8,但在项目开发中存在一个需求:在 ...
- STM32F429的特点
STM32F429 内核 Crotex M4 最高主频 180MHZ FPU 有 DSP指令集 有 最大SRAM 256K 备份域SRAM 有 最大FLASH 2MB GPIO最高翻转速度 90MHZ ...
- APICloud联合腾讯云推出“云主机解决方案“,各种福利等你拿
为了帮助开发者一站式打通云.开发.运维全流程服务,更全面提供基于自身业务情况的云服务器.数据库.存储等基础设施服务,APICloud联合腾讯云重磅推出“云主机解决方案“.开发者可通过控制台简单清晰的购 ...
- ST表竞赛模板
void RMQ_init(){//ST表的创建模板 ;i<n;i++) d[i][]=mo[i]; ;(<<j)<=n;j++) ;i+(<<j)-<n;i ...