zoukankan      html  css  js  c++  java
  • Javascript的异步与单线程

    一、前言

    我们都知道,javasript是一个单线程的语言;所谓单线程就是同一时间不能做两件事情,两段代码不能同时执行;因为这种机制,才避免了两段js同时对一个DOM节点进行渲染的冲突。但是也会因此产生一个问题,比如说有一个非常耗时的操作在js中执行,因为js是按顺序执行的,所以会导致代码一直卡在这个耗时的方法那里,从而造成页面假死的状态,为了解决这个问题,js也提供了一些解决方案,比 如Ajax、setTimeout、setInterval,提供了异步的解决方案。有人会说,那单线程和异步同时存在一个语言里不是冲突了吗?其实不然,js虽是单线程语言,但是浏览器不是单线程的啊,浏览器为js的执行分配了一个主线程,也可以通过某种方式另外开辟一个副线程去执行js中的耗时操作,然后通过callback的形式返回到主线程中去执行,所以说异步只是一种单线程的解决方案,并不能改变js语言作为一个单线程语言的本质。

    二、异步

    1、实现异步的方式(eventloop)事件轮询

    eventloop即事件轮询,是js实现异步的具体方式,当js按顺序执行的时候遇到异步函数,会将异步函数放在异步队列中,当同步函数执行完毕之后会轮询执行异步队列中的函数。 

    事件轮询会一直查询异步队列中是否存在异步函数,所以在第一个地步函数执行完成之后,等待了一秒之后会在异步队列中发现func2这个函数出现在异步队列中,于是事件轮询查询到这个函数,并将此函数放入主进程中执行。其中func1和func2均属于异步函数的回掉函数。

    2、异步的几个解决方案

    (1)jquery中的deffered

     1 function test() {
     2     var dt = $.Deferred()
     3     var wait = function(dt) {
     4         var task = function() {
     5             console.log('deffered is ok!')
     6             dt.resolve() //成功
     7             // dt.reject()  //失败
     8         }
     9         setTimeout(task, 1000)
    10         return dt.promise()
    11     }
    12     return wait(dt)
    13 }
    14 
    15 var w = test()
    16 // w.reject()    // 在这里执行reject()会导致接下来的函数走到error里,所以需要将上述返回对象改为返回promise
    17 $.when(w).then(function() {
    18     console.log('ok1')
    19 }, function() {
    20     console.log('error1')
    21 })
    22 w.then(function() {
    23     console.log('ok2')
    24 }, function() {
    25     console.log('error2')
    26 })

    Deffered对象中可以主动修改resove或reject,promise只能被动监听

    (2)Promise

    Promise在ES6中真是被列为标准,关于Promise这里只说几个使用场景,

    串联:即第二个异步的执行可能会依赖第一个异步执行的结果

     1 function loadImg(src) {
     2   var promise = new Promise((resolve, reject) => {
     3     var img = document.createElement('img')
     4     // throw new Error('this is a error!')  //抛出一个异常
     5     img.onload =function () {
     6       resolve(img)
     7     }
     8     img.onerror = function () {
     9       reject('picture onload error!') //传入一个信息会走到catch中捕捉到错误
    10     }
    11     img.src = src
    12   })
    13   return promise
    14 };
    15 //promise串联加载
    16 var src = '**********************'
    17 var result = loadImg(src)
    18 var src1 = '**********************'
    19 var result1 = loadImg(src1)
    20 
    21 result.then(() => {
    22   console.log('first')
    23   return result1        // 此处返回result1Promise实例,若不返回则默认返回result
    24 }).then(() => {
    25   console.log('second')
    26 }).catch((error) => {
    27   console.log(error)
    28 })

    Promise.all传入一个数组,即当所有的一部函数全部执行完毕之后才会走的回调函数

    1 Promise.all([result, result1]).then(function(res) {
    2     // 全部执行完毕之后的逻辑
    3 })

    Promise.race同样传入一个数组,即只要有一个异步函数执行完毕之后都会走回调函数

    1 Promise.race([result, result1]).then(function(res) {
    2     // 全部执行完毕之后的逻辑
    3 })

    (3)async/await

    此方法不在ES6标准中,ES7引入,还没有成为标准,相比于Promise它只是在执行回调的方式不同,其后面还是跟的一个Promise,只不过Promise后面的.then依旧使用的是异步的回调方式,而async则是使用同步的使用方式

    1 const load = async function() {
    2     const result = await loadImg(src)
    3     console.log(result.width)
    4     const result1 = await loadImg(src1)
    5     console.log(result1.width)
    6 }

    以上为本次讨论内容,不足之处还请指正

  • 相关阅读:
    IIS无法显示 XML 页
    asp.net实现sql存取图片
    微软的面试题
    IIS配置.Net问题大全
    Asp.Net调用WebService
    生活本无常,前路更精彩
    【转载】碰到讨厌的老板怎么办
    xxxx不必xx尽,留些xxxx
    【BLOG】Mr梵谷
    机会,从来都是留给有准备的你
  • 原文地址:https://www.cnblogs.com/gaosong-shuhong/p/9280863.html
Copyright © 2011-2022 走看看