• js单线程和js异步操作的几种方法


    一、为什么JavaScript是单线程?
    JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
    JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
    这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?
    单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
    一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
    同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
    异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
    -------------------------------------------------------------------------
    js的异步操作的几种方法:
    1.回调函数 function fn1 () { console.log('方法一') } function fn2 () { setTimeout(() => { console.log('方法二') }, 1000) } function fn3 () { console.log('方法三') } 现在我希望可以依次执行fn1,fn2,fn3。为了保证fn3在最后执行,我们可以把它作为fn2的回调函数: function fn2 (f) { setTimeout(() => { console.log('方法二') f() }, 1000) } fn2(fn3) 由此可以看出fn2和fn3完全耦合在一起,如果多了就耦合度很高; ----------------------------------------------------------------------------- 2.事件发布/订阅(可以在es5下相当优雅地处理异步操作) fn1,fn2,fn3都可以视作一个事件的发布者,只要执行它,就会发布一个事件。这个时候,我们可以通过一个事件的订阅者去批量订阅并处理这些事件,包括它们的先后顺序。 class AsyncFunArr { constructor (...arr) { this.funcArr = [...arr] } next () { const fn = this.funcArr.shift() if (typeof fn === 'function') fn() } run () { this.next() } } const asyncFunArr = new AsyncFunArr(fn1, fn2, fn3) 然后在fn1,fn2,fn3内调用其next()方法; function fn1 () { console.log('方法一') asyncFunArr.next() } function fn2 () { setTimeout(() => { console.log('方法二') asyncFunArr.next() }, 500) } function fn3 () { console.log('方法三') asyncFunArr.next() } //依次输出方法一、方法二、方法三 --------------------------------------------------------------------------------- 3.Promise function fn1 () { console.log('方法一') } function fn2 () { return new Promise((resolve, reject) => { setTimeout(() => { console.log('方法二') resolve() }, 500) }) } function fn3 () { console.log('方法三') } 其中fn2是一个返回Promise的异步函数,现在按顺序执行它们; fn1() fn2().then(() => { fn3() }) //依次输出方法一、方法二、方法三 --------------------------------------------------------------------------------- 4.generator(这种方式还是不够优雅) function fn1 () { console.log('方法一') } function fn2 () { setTimeout(() => { console.log('方法二') af.next() }, 500) } function fn3 () { console.log('方法三') } function* asyncFunArr (...fn) { fn[0]() yield fn[1]() fn[2]() } const af = asyncFunArr(fn1, fn2, fn3) af.next() //依次输出方法一、方法二、方法三 如果有多个异步函数,那么这个generator函数肯定得改写,而且在语义化的程度来说也有一点不太直观。 ------------------------------------------------------------------------------------ 5.优雅的async/await(最新版本的Node已经可以原生支持async/await写法了,通过各种pollyfill也能在旧的浏览器使用。) function fn1 () { console.log('方法一') } function fn2 () { return new Promise((resolve, reject) => { setTimeout(() => { console.log('方法二') resolve() }, 500) }) } function fn3 () { console.log('方法三') } async function asyncFunArr () { fn1() await fn2() fn3() } asyncFunArr() //依次输出方法一、方法二、方法三 异步的操作都返回Promise,需要顺序执行时只需要await相应的函数即可,这种方式在语义化方面非常友好;

     

  • 相关阅读:
    mysql常用函数
    主程Ry访谈录
    mongodb spring anno 查询
    mongodb 查询少少优化
    jquery table thead drop
    ubuntu 配置java,eclipse ,flex,zend,php,TomCat环境
    mongodb shell
    TCP/IP Sockets in Java 源码
    java 断点下载
    直线生成 DDA
  • 原文地址:https://www.cnblogs.com/lhl66/p/8974718.html
Copyright © 2020-2023  润新知