美文网首页工作生活
javascript异步理解

javascript异步理解

作者: 海的那一边 | 来源:发表于2019-07-04 20:19 被阅读0次

    javascript是单线程编程,意思就是javascript引擎一次只能执行一个语句。这样在出现长时间的请求的话,会阻塞主线程,为了不阻塞主线程,出现了javascript异步的概念。

    javascript 同步异步理解:
    设想这样的情景,你现在路过一个炸鸡店,闻着特别香,你实在抵挡不住炸鸡的诱惑,你就走上前,买了一份炸鸡。
    同步的情况是:你点了一份炸鸡,然后你站到跟前等着啥也不干,炸鸡好了之后,你付钱给老板。
    异步的情况是:你点了一份炸鸡,然后老板给你一张号码单,你把钱付了,玩着手机等,炸鸡好了之后,老板再叫你。

    同步代码:

    const makeChicken = () => {
      console.log('炸鸡好了')
    }
    console.log('我要吃炸鸡')
    makeChicken()
    console.log('给你炸鸡钱')
    console.log('玩手机')
    

    执行结果:

    我要吃炸鸡
    炸鸡好了
    给你炸鸡钱
    玩手机
    

    异步代码:

    const makeChicken = () => {
      setTimeout(() => {
        console.log('炸鸡好了')
      }, 2000)
    }
    console.log('我要吃炸鸡')
    makeChicken()
    console.log('给你炸鸡钱')
    console.log('玩手机')
    

    执行结果:

    我要吃炸鸡
    给你炸鸡钱
    玩手机
    炸鸡好了
    

    异步实现逻辑:


    image.png

    事件循环、web APIs 和消息队列不是JavaScript引擎的一部分,它们是浏览器端的JavaScript运行环境或者Nodejs端的JavaScript运行环境的一部分。在Nodejs中,web APIs被C/C++ APIs替代。

    当上面的代码加载在浏览器中,console.log('我要吃炸鸡'),被推到栈中然后当结束时从栈中被移除。然后,makeChicken()触发,然后它被推到了栈的顶部。

    接下来setTimeOut( )函数被调用,所以它被推到了栈顶。setTimeOut( )有两个参数:一是回调,二是毫秒数。

    这个setTimeOut( )方法在web APIs环境中开始了一个2秒的计时器。此时,setTimeOut( )执行完毕并被移出栈。之后,console.log('给你炸鸡钱'),被推到栈里,执行完后被移除。

    同时,计时器到期了,现在这个回调被推到了消息队列。但是这回调不会被立即执行,这里就是事件循环插手的地方。

    事件循环的作用是查看调用栈并确定调用栈是否为空。 如果调用栈为空,它会查看消息队列以查看是否有任何挂起的回调等待执行。

    在上面的例子中,消息队列中有一个回调,并且此时调用栈已经空了。 因此,事件循环将回调推到栈顶部。

    之后, console.log('炸鸡好了')被推到栈顶部,执行完后从堆栈中弹出。 此时,回调已执行完毕,因此被从栈中移除,程序最终完成。

    异步的几种实现:
    1)回调函数:
    意思就是等到炸鸡好了再叫你。

    function getYourFood() {
      console.log('给你炸鸡')
    }
    
    function getChicken(callback) {
      console.log('准备制作炸鸡')
      setTimeout(() => {
        console.log('炸鸡制作完成')
        callback()
      }, 2000)
    }
    
    getChicken(getYourFood)
    

    执行结果:

    我要炸鸡
    准备制作炸鸡
    炸鸡制作完成
    给你炸鸡
    

    2)promise
    使我们可以主动的去执行后面的动作,而不是把回调函数给一个方法等在这个方法内部调用。

    function makeChicken() {
      return new Promise(((resolve) => {
        console.log('准备制作炸鸡')
        setTimeout(() => {
          resolve('炸鸡成功')
          console.log('炸鸡制作完成')
        }, 2000)
        console.log('炸鸡制作中')
      }))
    }
    function getYourFood() {
      return new Promise(((resolve) => {
        resolve('炸鸡好了')
      }))
    }
    console.log('我要炸鸡')
    makeChicken().then(() => {
      getYourFood().then((seccess) => {
        console.log(seccess)
      })
    })
    

    执行结果:

    我要炸鸡
    准备制作炸鸡
    炸鸡制作中
    炸鸡制作完成
    炸鸡好了
    

    3)async await
    使异步代码看起来就是同步代码。我们添加一个关键字async让引擎知道哪个函数触发是异步的并且会返回一个promise,让我们使用await。

    function makeChicken() {
      return new Promise(((resolve) => {
        console.log('准备制作炸鸡')
        setTimeout(() => {
          resolve('炸鸡成功')
          console.log('炸鸡制作完成')
        }, 2000)
        console.log('炸鸡制作中')
      }))
    }
    function getYourFood() {
      return new Promise(((resolve) => {
        resolve('炸鸡好了')
      }))
    }
    async function OrderChicken() {
      await makeChicken()
      const result = await getYourFood()
      console.log(result)
    }
    console.log('我要炸鸡')
    OrderChicken()
    

    运行结果:

    我要炸鸡
    准备制作炸鸡
    炸鸡制作中
    炸鸡制作完成
    炸鸡好了
    

    我觉得下面链接的有关异步的讲解特别好。

    参考链接:
    [译]理解异步JavaScript-事件循环https://mbd.baidu.com/newspage/data/landingshare?pageType=1&isBdboxFrom=1&context=%7B%22nid%22%3A%22news_9071904341435333508%22%2C%22sourceFrom%22%3A%22bjh%22%7D

    [翻译]JavaScript异步进化史:Callbacks,Promises,Async/Await 上
    https://mbd.baidu.com/newspage/data/landingshare?context=%7B%22nid%22%3A%22news_8754335365643315921%22%2C%22sourceFrom%22%3A%22bjh%22%7D&type=news

    [翻译]JavaScript异步进化史之下篇
    https://mbd.baidu.com/newspage/data/landingshare?context=%7B%22nid%22%3A%22news_9356479249406614478%22%2C%22sourceFrom%22%3A%22bjh%22%7D&type=news

    相关文章

      网友评论

        本文标题:javascript异步理解

        本文链接:https://www.haomeiwen.com/subject/olmlhctx.html