专栏首页小码农学习笔记JavaScript 中同步与异步知识点整理
原创

JavaScript 中同步与异步知识点整理

同步与异步

在 ES5 中,异步编程的传统解决方案是通过回调函数或事件监听。undefined在 ES6 中,Promise 成为了异步编程的一种更合理更强大的解决方案。undefined在 ES7 中,async/await 优化了 ES6 异步编程的解决方案,比 Promise 更加优美。

同步与异步概念

同步:同步就是后一个任务等待前一个任务执行完毕后,再执行,执行顺序和任务的排列顺序一致。

异步:异步是非阻塞的,异步逻辑与主逻辑相互独立,主逻辑不需要等待异步逻辑完成,而是可以立刻继续下去。

举个例子:

console.log('a');
console.log('b');
console.log('c');

setTimeout(() => {console.log('我是一段异步操作')}, 2000);

console.log('d');
console.log('e');

从以上代码的输出结果可以看出,异步函数的好处是不会阻塞主任务

再举个例子:

console.log('a');
console.log('b');
console.log('c');

setTimeout(() => {console.log('我是写在前面的异步操作')}, 2000);

setTimeout(() => {console.log('我是写在后面的异步操作')}, 500);

console.log('d');
console.log('e');

上述代码的执行结果表明:当有多个异步函数时,跟书写顺序无关,谁先返回,就先执行谁的回调

ajax(jQuery)

$.ajax 是 jQuery 中一个异步请求的方法,它的用法如下代码所示:

console.log(1);

$.ajax({
  type: "get",
  url: "https://www.fedbook.cn/apis/articles/list/",
  success: function(res) {
    console.log(res)
  }
});

console.log(2);

上述代码是一种传统异步编程的解决方案:通过回调函数实现。但它有一个致命的缺点,就是容易写出回调地狱

假设多个请求存在依赖性,你可能就会写出如下代码:

ajax(url, () => {
  // 处理逻辑
  ajax(url1, () => {
    // 处理逻辑
    ajax(url2, () => {
      // 处理逻辑
    })
  })
})

Promise

Promise 是 ES6 中异步编程的一种解决方案,比传统的解决方案(回调函数或事件监听)更合理且更强大。

它有三个状态:

  • pending:初始状态
  • fulfilled:操作成功
  • rejected:操作失败

当 promise 状态发生改变,就会触发 then() 里的响应函数处理后续步骤。

状态改变,只有两种可能:

  • 从 pending 变为 fulfilled
  • 从 pending 变为 rejected

基础用法

下述代码演示了 Promise 基础用法:

var promise = new Promise(function(resolve, reject) {
  if (true) {
    resolve('success'); // 异步请求成功,将请求结果 resolve 出去
  } else {
    reject('fail'); // 异步请求失败,将错误信息 reject 出去
  }
});

promise.then(res => {
  console.log(res); // 成功 resolve('success')
}).catch(error => {
  console.log(error); // 失败 reject('fail')
})

Promise.all

Promise.all 可以将多个 Promise 实例包装成一个新的 Promise 实例。同时,成功和失败的返回值是不同的。

成功的时候返回的是一个结果数组,数组中值的顺序与传入 promise 的顺序相同;而失败的时候则返回最先被reject失败状态的值

下述代码演示了 Promise.all 的用法:

let p1 = new Promise((resolve, reject) => {
  resolve('success 1');
});
let p2 = new Promise((resolve, reject) => {
  resolve('success 2');
});
let p3 = new Promise((resolve, reject) => {
  reject('fail');
});

Promise.all([p1, p2]).then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
});
// ['success 1'. 'success 2']

Promise.all([p1, p2, p3]).then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
})
// 'fail'

Promise.race

顾名思义,Promise.race 就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3]) 里面哪个结果获得的快,就返回那个结果,不管结果本身时成功状态还是失败状态。

下述代码演示了 Promise.race 的用法:

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success');
  }, 1000)
});
let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('fail');
  }, 500)
});

Promise.race([p1, p2]).then(result => {
  console.log(result);
}).catch(error => {
  console.log(error);
});
// 'fail'

async/await

async/await 是 ES7 的新标准,也是用来处理异步的,是目前异步的终极解决方案。它其实是 Generator 函数的改进,背后原理就是 Promise。

async 意义

  1. 在函数前加上 async,函数的任何返回值都会被包装成 Promise
  2. 函数内部引入了 await,如果不用 async 会报错

await 意义

  1. 求值关键字,计算返回的 Promise 中的值,或者表达式(await 100*100
  2. 阻塞当前线程

基础用法

下述代码演示了 async/await 基础用法:

这段代码主要体现了:await 会阻塞后面的代码,等主程序执行完,再回来执行。

此外,await 后面既可以是一个 async 函数(返回 Promise 对象),也可以是一个正常函数。

async function f1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {resolve('world')}, 2000);
  });
}

async function f2() {
  var result = await f1();
  // 阻塞
  console.log('hello');
  console.log(result);
}

f2();
// 等待两秒后,才依次打印出 'hello','world'

错误处理

async/await 中的错误处理需要通过 try/catch 来实现,否则一旦 reject,会直接抛出错误(Uncaught (in promise) xxx),后面的代码就都不会执行了。

async/await 结合 try/catch 的代码如下所示:

async function f1() {
  return Promise.reject('fail');
  // 与下面代码等价
  // return new Promise((resolve, reject) => {reject('fail')})
}

async function f2() {
  try {
    let result = await f1();
  } catch (e) {
    console.log(e);
  }
}

f2();
// 'fail'

总结

本文简单介绍了 Promise 与 async/await 的用法,如果需要了解更多,可以阅读阮一峰老师编写的《ES6标准入门(第3版)》中 Promise 对象async 函数 两个章节。


文章持续更新,本文 GitHub 前端修炼小册 已经收录,欢迎 Star。如对文章内容有不同见解,欢迎留言交流。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C# 委托 、事件、同步、异步知识点归纳

    1.声明一个委托类型。委托就像是‘类'一样,声明了一种委托之后就可以创建多个具有此种特征的委托。(特征,指的是返回值、参数类型)

    vv彭
  • Java开发中同步异步、阻塞非阻塞知识总结

    一般来说,同步是最简单的编程方式,而异步编程虽然需要一定的技术和工作量,但是却能提升系统性能。对于阻塞与非阻塞,阻塞方式的实时响应性更好,但是挂起与唤醒线程的性...

    用户1289394
  • linux线程间的同步与互斥知识点总结

    在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性。

    砸漏
  • 【SpringBoot WEB系列】异步请求知识点与使用姿势小结

    在 Servlet3.0 就引入了异步请求的支持,但是在实际的业务开发中,可能用过这个特性的童鞋并不多?

    一灰灰blog
  • 7个 Javascript 面试题及回答策略 [每日前端夜话0x30]

    这个问题用来评估基础编码知识。答案可以有多种,所以应该注意倾听具体的问题,并尽量全面回答,来展示自己对单体应用与微服务架构的理解。

    疯狂的技术宅
  • 前端数据获取之Ajax与Fetch (一)

    Ajax,读作”阿贾克斯“,这个是每一个web开发者必掌握的一门技术,现在咱们打开一个网页,页面上数据多多少少都会有它的一些参与,来获取数据,但也并不是所有的数...

    用户1462769
  • 【前端进阶】深入浅出浏览器事件循环【内附练习题】

    我们看一个很经典的图,这张图基本可以概括了事件循环(该图来自演讲—— 菲利普·罗伯茨:到底什么是Event Loop呢?| 欧洲 JSConf 2014[1])...

    GopalFeng
  • 【JS】239-浅析JavaScript异步

    一直以来都知道 JavaScript是一门单线程语言,在笔试过程中不断的遇到一些输出结果的问题,考量的是对异步编程掌握情况。一般被问到异步的时候脑子里第一反应就...

    pingan8787
  • 【JS】368- 浅析JavaScript异步

    一直以来都知道 JavaScript是一门单线程语言,在笔试过程中不断的遇到一些输出结果的问题,考量的是对异步编程掌握情况。一般被问到异步的时候脑子里第一反应就...

    pingan8787
  • Node.js 异步异闻录

    提到 Node.js, 我们脑海就会浮现异步、非阻塞、单线程等关键词,进一步我们还会想到 buffer、模块机制、事件循环、进程、V8、libuv 等知识点。本...

    牧云云
  • JavaWeb学习-Ajax-1-Ajax简介

    进入到一个新的知识点的学习,这个知识点叫做Ajax,指的是异步的javascript和xml,Ajax不是一种编程语言,而是一种用于创建更好更快,交互性更强的w...

    凯哥Java
  • 快速学习-登录功能实现-页面中错误提示

    6) JSP的脚本元素 ① 脚本片段是嵌入到JSP中Java代码段,格式以<%开头,%>结尾,两个%号之间就可以编写Java代码了

    cwl_java
  • 谈一谈javascript异步

    我们知道JavaScript的单线程的,这与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程...

    陌上寒
  • 前端技能自检

    前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快,是其他技术所不能比拟的。

    grain先森
  • chrome浏览器架构学习

    在从事前端开发过程中,浏览器作为最重要的开发环境,浏览器基础是前端开发人员必须掌握的基础知识点,它贯穿着前端的整个网络体系。对浏览器原理的了解,决定着编写前端代...

    薛定喵君
  • 5分钟详解chrome浏览器架构知识

    在从事前端开发过程中,浏览器作为最重要的开发环境,浏览器基础是前端开发人员必须掌握的基础知识点,它贯穿着前端的整个网络体系。对浏览器原理的了解,决定...

    薛定喵君
  • 一名【合格】前端工程师的自检清单

    前端开发是一个非常特殊的行业,它的历史实际上不是很长,但是知识之繁杂,技术迭代速度之快是其他技术所不能比拟的。

    ConardLi
  • 完整的Java学习路线

    框架师
  • 技术大咖之路:LingyuCoder的学习经历

    本文转载自:https://github.com/qiu-deqing/FE-learning

    疯狂的技术宅

扫码关注云+社区

领取腾讯云代金券