zoukankan      html  css  js  c++  java
  • 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相应的函数即可,这种方式在语义化方面非常友好;

     

  • 相关阅读:
    201521044091《Java程序设计》第7周学习总结
    201521044091《java程序设计》第四次总结
    201521044091 《java程序设计》第八周学习总结
    201521044091 《Java程序设计》第5周学习总结
    201521044091 《Java程序设计》第2周学习总结
    201521044091 《Java程序设计》第3周学习总结
    MySQL设置字符集CHARACTER SET
    Create My MySQL configuration by Percona
    How to use jQuery to manipulate Cookies
    How to use OpenXml to import xml data to Sql server
  • 原文地址:https://www.cnblogs.com/lhl66/p/8974718.html
Copyright © 2011-2022 走看看