前端原理_异步与单线程

单线程

  • 什么是单线程?
Javascript语言的执行环境是"单线程"(single thread)
所谓"单线程",就是指一次只能完成一件任务。
如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。

执行JS代码的是JS引擎(JS引擎就是单线程,所以叫JS引擎线程)
  • 单线程的好处与产生的问题
好处:
实现起来比较简单,执行环境相对单纯

产生问题:
只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。

常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),
导致整个页面卡在这个地方,其他任务无法执行。
  • 单线程解决方案
为了单线程(JS引擎线程)不卡死,所以出现“ 异步 ”这个解决方案

异步

  • 前端中有哪些操作属于异步操作?
1、定时器
2、ajax请求
3、io操作

共性:一些耗时操作一般使用异步

注意:事件绑定不属于异步操作,只是采用了异步编程处理方式(回调函数)而已
  • 异步编程处理方式
1、回调函数
2、Promise
3、await/async  (最好解决方案)

回调函数

最早出现的处理异步编程的方式(兼容性最好,但不推荐)

回调函数方式最大的问题是:回调地狱
回调地狱是代码阅读性差,项目维护性差

setTimeout(function (name) {
  var catList = name + ',';

  setTimeout(function (name) {
    catList += name + ',';

    setTimeout(function (name) {
      catList += name + ',';
      
    }, 1, 'Lynx');
    
  }, 1, 'Jaguar');

}, 1, 'Panther');

如果当前网络请求需要依赖前一个网络请求,以此类推,这就叫回调地狱

Promise

ES6出现的处理异步编程的方式,主要是为了解决 回调地狱问题
  • 三种状态
1、pending:初始状态,后面then()的传参函数不会执行
2、resolved:成功状态
3、rejected:失败状态
  • 基本用法
通过Promise构建函数,创建一个处理异步任务的对象

箭头函数方式:
const p = new Promise((resolve, reject)=>{ });

传统方式
const p = new Promise(function(resolve, reject){})
注意:
1、传参函数的 函数体会马上执行,而且是 同步
2、传参函数的内部没有调用resolve()或reject()方法,那么Promise对象的状态依旧是 pending,后面 then()不会执
3、传参函数的函数体内,主要放的是 异步操作代码
4、传参函数的函数体内, 调用resolve()时,Promise实例的状态将 由pending转resolved
5、传参函数的函数体内, 调用reject()时,Promise实例的状态将 由pending转rejected
6、resolve()或者reject(),只能传一个参数
  • 实例方法 then
用法:
const p = new Promise((resolve, reject)=>{ });
p.then(data=>{ }).then(data=>{ })

then函数的返回值:
是一个全新的Promise对象,与调用then()的Promise对象不同

1、p为resolved状态下,then传递的函数中,如果没有返回值:
const pp = p.then(data=>{
    console.log('go');
});

那么pp的状态继承p是resolved,而携带的参数为undefined

2、p为resolved状态下,then传递的函数中,如果有返回值是非Promise对象:
const pp = p.then(data=>{
    return '你好';
});

那么pp的状态继承p是resolved,而携带的参数为'你好'

3、p为resolved状态下,then传递的函数中,如果有返回值是Promise对象:
const pp = p.then(data=>{
    return new Promise((resolve, reject)=>{
        reject();
    });
});

那么pp的状态是rejected(状态可以修改),而携带的参数为undefined

4、p为rejected状态下,then传递的函数中没有传递第二个函数时:
const pp = p.then(data=>{ });

那么pp的状态继承p是rejected,而携带的参数也继承p
注意:
1、如果调用resolve()或者reject()方法时,没有传一个参数,那么then()中传的函数就没有接收参数, data为undefined
2、只要Promise状态不是 pending,那么then中传的 函数就会执行一般只传一个函数作为参数
3、调用then()时,只要不传函数作为参数,那么 生成的新Promise对象,状态继承,参数也继承
  • 实例方法 catch
主要用于处理 rejected失败状态
.catch(error=>{ })只是一个then的别名

等同于
then(null, error=>{ }) 或 then(undefined, error=>{ })

catch的返回值:
也是一个全新的Promise对象,该对象的状态和携带参数 与 then四种情况一样

当没有返回值时,状态继承是rejected,而携带的参数为undefined
  • 静态方法 all
多个Promise对象并行执行,最后所有的Promise对象执行完成后,再执行最后的Promise对象
  • 静态方法 race

await/async

ES7出现的处理异步编程的方式(强烈推荐)

JS异步实现原理

浏览器中的JS引擎是单线程的(解析JS是单线程的),但浏览器是多进程的
  • 任务类别

你可能感兴趣的