• JavaScript 异步编程


    博客地址:https://ainyi.com/96

    众所周知,JavaScript 是单线程的,但异步在 js 中很常见,那么简单来介绍一下异步编程

    同步编程和异步编程

    同步编程,计算机一行一行按顺序依次执行代码,当前代码任务执行时会阻塞后续代码的执行;典型的请求-响应模型就是这样,当请求调用一个函数或方法后,需等待其响应返回,然后执行后续代码

    异步编程,执行当前任务时(执行中),也可直接执行下一个任务;多个任务并发执行

    这就涉及到两个比较容易混淆的概念了:并行并发

    并行(parallel):指同一时刻内多任务同时进行;如下图:
    755737372912ea8e89c4007.jpg


    并发(concurrency):指在同一时间段内,多任务同时进行着,但是同一时刻,只有某一任务执行。使得在宏观上具有多个进程同时执行的效果,但在微观上只是把时间分成若干段,使多个进程快速交替地执行;如下图:
    7557373da64ffd6d1effaac.jpg

    异步机制

    由上面并发的解释,可以知道单线程可以实现类似多线程机制的这种执行方式;那么 JavaScript 单线程的异步编程可以实现多任务并发执行

    重点实现 js 异步的方式,就是事件循环,之前写过关于事件循环的例子,可看:JavaScript 事件循环、异步和同步

    事件循环

    事件循环涉及到两个概念:消息队列、任务

    消息队列:也叫任务队列,存储待处理消息及对应的回调函数或事件处理程序
    任务:js 区分同步任务和异步任务,代码执行就是在执行任务,也就是对应同步和异步的代码块

    首先 JavaScript 的同步任务是进入主线程的执行栈执行;异步任务则进入消息队列(任务队列),一个存储着待执行任务的队列,严格按照时间先后顺序执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行

    事件循环的流程:检查主线程执行栈是否为空,先执行执行栈中的同步任务,异步任务(回调函数)放入任务队列中,一旦执行栈中的所有的同步任务执行完毕,就会取出任务队列的首部压入执行栈,开始执行,然后继续检查执行栈是否为空,重复这个过程

    简单来说:事件循环其实就是入栈出栈的循环

    这样就能实现异步方式

    js 的异步方式

    • setTimeout
    • ajax
    • Promise
    • Generator

    setTimeout
    即使将时间设置为 0,也会延迟执行,即异步执行。具体可看:setTimeout 时间参数为 0 的探讨

    setTimeout(() => { 
       console.log('Hello!')
    }, 0)
    

    ajax

    let xhr = new XMLHttpRequest()
    xhr.onreadystatechange = function() { 
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 ) {       
        console.log(xhr.responseText)
      } else {   
        console.log( xhr.status)
      }
    }
    xhr.open('GET', 'url', false)
    xhr.send()
    

    xhr.open 中第三个参数默认为 false 异步执行,改为 true 时为同步执行


    Promise
    promise 就经常使用了,平常使用 axios 作为请求接口的方式,就是封装了 Promise。当然也可以自己封装使用
    具体可看:ES6 Promise 解析及详解三个状态

    const promise = new Promise(resolve => {
      setTimeout(() => {
        resolve('hello')
      }, 1000)})
    promise.then(value => {
      console.log(value, 'world')
    }, error =>{
      console.log(error, 'unhappy')
    })
    

    Generator
    generator 也叫做生成器,它是 ES6 中引入的一种新的函数类型,内部拥有能够多次启动和暂停代码执行的强大能力,那么也能够用于异步编程中

    const axios = require('axios')
    
    const foo = function () {
      return axios({
        method: 'GET',
        url: 'https://cosmos-alien.com/some.url'
      })
    }
    
    const main = function *() {
      try {
        let result = yield foo()
        console.log(result)
      } catch (err) {
        console.error(err)
      }
    }
    
    let it = main()
    let p = it.next().value
    
    p.then((data) => {
      it.next(data)
    }, (err) => {
      it.throw(err)
    })
    

    博客地址:https://ainyi.com/96

  • 相关阅读:
    CodeforcesBeta Round #19 D. Points 离线线段树 单点更新 离散化
    挑战练习题3.3 POJ 2886 Who Gets the Most Candies? 树状数组
    hdu4288 Coder 离线线段树 单点更新 区间求和 离散化?
    zoj 1610 Count the Colors 线段树 区间更新
    51nod 1307 绳子与重物 二分+dfs / 并查集
    51nod 1116 K进制下的大数 暴力/数论
    Wannafly2016-12-27 SPOJ-INTSUB 数学
    C++——Vector
    LEDE Project
    Raspberry Pi 3 with Openwrt
  • 原文地址:https://www.cnblogs.com/ainyi/p/13673413.html
Copyright © 2020-2023  润新知