一、概念

(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){});
//两个形参: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有三种情况:

  1. 普通值:除了promise对象,和thenable对象的所有值,生成一个已完成的promise对象并且PromiseValue的值就是传入的value
  2. promise对象,直接返回该value
  3. 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)的更多相关文章

  1. 浅谈JS异步轮询和单线程机制

    单线程特点执行异步操作 js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步 ...

  2. 浅谈js异步

    大家都知道,js是一个单线程的语言(只有一个线程来执行js函数),所以如果某一个函数执行任务耗时比较长的话,就会造成阻塞,使得后续任务一直处于等待状态. 一.阻塞示例 function f1(){ ; ...

  3. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  4. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  5. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  6. 浅谈 js 字符串之神奇的转义

    原文:浅谈 js 字符串之神奇的转义 字符串在js里是非常常用的,但是你真的了解它么?翻阅<MDN String>就可以了解它的常见用法了,开门见山的就让你了解了字符串是怎么回事. 'st ...

  7. 浅谈 js 正则之 test 方法

    原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. var re = /\d/; console. ...

  8. 浅谈 js 数字格式类型

    原文:浅谈 js 数字格式类型 很多人也许只知道 ,123.456,0xff 之类的数字格式.其实 js 格式还有很多数字格式类型,比如 1., .1 这样的,也有 .1e2 这样的. 可能有人说这是 ...

  9. 浅谈 js 语句块与标签

    原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...

随机推荐

  1. FineReport报表和水晶报表的比较

    FineReport报表和水晶报表的比较 FineReport报表软件针对复杂格式的报表数据及Web报表的展现,通过多源分片.不规则分组.双向扩展来轻松拖拽做复杂格式的报表,制作报表从此摆脱了复杂的S ...

  2. Python11_文件的读写

    1.打开和关闭文件(文件对象的方法open,close) file object = open(file_name [, access_mode][, buffering]) 各个参数的细节如下: f ...

  3. pycharm 更改创建文件默认路径

    1.操作 依次找到以下路径修改为自己想要的路径即可:PyCharm——>Settings——>Appearance&Behavior——>System Setting——&g ...

  4. 解析GMT+N时区,返回日期类型

    涉及到正则表达式,时区转换. /** * * 按格式 yyyy-MM-dd HH:mm:ss 以指定GMT时区进行解析,返回对应的当前系统时区当地时间. * @param dateString  格式 ...

  5. linux-free、lscpu、

    1.free -h 以人类可读的形式显示 -m 以MB为单位显示 -w 将buffers和cache分开单独显示(针对centos7系统) centos6上: centos7上: -s 动态查看内存信 ...

  6. vue学习笔记(六)表单输入绑定

    前言 在上一章vue学习笔记(四)事件处理器这一篇博客的内容中,我们已经了解vue是如何绑定事件的,而本篇博客主要讲解的是vue中表单输入的绑定,通常我们自己提交信息的时候都是通过表单将信息到服务器的 ...

  7. 20191121-3 Final阶段贡献分配规则

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/10063 ”组长”组final阶段贡献分分配规则 组里五位成员分别有入团队 ...

  8. Django 项目目录重构

    原因 一个完整的项目下来, 会涉及很多模块, 文件和资源, 对Django默认的文件目录结构基础上进行重构, 会使得我们的项目结构更加清晰, 便于后期管理 重构 """ ...

  9. jmeter 5.1版本更新说明

    版本5.1 摘要 新的和值得注意的 不兼容的变化 Bug修复 改进 非功能性变化 已知问题和解决方法 谢谢 新的和值得注意的 核心改进 JDBC测试已得到改进,能够设置init SQL语句并添加与不支 ...

  10. [NoSQL] 从模型关系看 Mongodb 的选择理由

    往期:Mongodb攻略 回顾 Mongodb 与关系型数据库的对应关系: MySQL   MongoDB database(数据库) database(数据库) table(表) collectio ...