美文网首页
你不知道的JavaScript 同步异步

你不知道的JavaScript 同步异步

作者: Nickyzhang | 来源:发表于2018-01-16 10:24 被阅读29次

写在前面的话

setTimeout是我们学习JavaScript基础都必须面对的问题,也许当时你搞懂了,但是过一段时间就又忘记了。最近事情不多,我将梳理出for + setTimeout相关的知识点,以及使用Promiseasync/await来加深对异步、同步的理解

setTimeout

直接进入正题:
for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}

也许我们希望输出的是 1,2,3,4,5,但实际情况是我们输出了5,5,5,5,5,这到底是为什么呢?
由JS的运行机制中我们得知:当线程中没有任何同步代码的前提下才会执行异步代码。我们的for循环时同步的,但是setTimeout是异步的,由此就造成了输出5,5,5,5,5这种情况。

通过一顿胡乱分析我们得出假设:只要保证里面的也变成同步的是不是就可以了呢?

方式①

for(var i = 0; i < 5; i++){
    setTimeout(function(){
        console.log(i);
    }, i*1000)
}

这里使用的是最简单的方式:动态的改变延迟的时间。
因为for循环时同步的,而setTimeout是异步的,所以会先把for循环执行完毕,然后再执行内部的setTimeout,所以输出结果为每隔1秒输出一个5

方式②

for (var i = 0; i < 5; i++) { 
  (function(j){
    setTimeout(function (){
      console.log(j); 
     },1000); 
  })(i); 
}

我们通过设置一个立即执行函数(IIFE),这样就能保证里面和外面的是同步执行的。

方式③

function output(i){
    setTimeout(function(){
        console.log(i);
    }, 1000)
}

for(var i = 0; i < 5; i++){
    output(i);
}

这里其实和第一种方法类似,只不过我们把这个函数单独拿出来,并把index值当做函数的参数来传递

方式④

for(let i = 0; i < 5; i++){
    setTimeout(function(){
        console.log(i);
    }, 1000)
}

letES6语法,for循环代码块构成一个作用域,里面的内容引用了上层作用域的变量 i,并最终形成五个闭包,而for使用var时,还是ES5的写法,for代码块没有形成作用域,所以里面的function不构成闭包。同理我们的方式①方式②都形成了闭包函数。

如果我们需要最后一个延迟5秒,其余的都是延迟1秒,我们就可以用到ES6的语法--Promise,下面我们用Promise实现这一情况

方式⑤

const task = [];
const output = (i) => new Promise(function(resolve, reject){
    setTimeout(function(){
        console.log(i);
        resolve();
    }, i*1000)
})
for (var i = 0; i<5; i++){
    task.push(output(i));
}
Promise.all(task).then(() => {
    setTimeout(() => {
        console.log(i);
    }, 5000);
})

这里采用了Promise解决异步的方式,在ES7中解决异步还有async/await的方式

方式⑥

const sleep = (timeount) => new Promise((resolve) => {
    setTimeout(resolve, timeount);
});

Func = async () => {
    for(var i = 0; i<5; i++){
        await sleep(1000);
        console.log(i);
    }
    await sleep(5000);
    console.log(i);
}

this.Func();

async 表示这是一个async函数,await只能用在这个函数里面;
await 表示在这里等待promise返回结果了,再继续执行;
await 后面跟着的应该是一个promise对象,否则没有同步效果

相关文章

  • AJAX-全集

    同步+异步 Ajax同步+异步 JavaScript之(AJAX) JQuery之(AJAX) JQuery-有f...

  • 你不知道的JavaScript 同步异步

    写在前面的话 setTimeout是我们学习JavaScript基础都必须面对的问题,也许当时你搞懂了,但是过一段...

  • ajax json

    一、ajax: async javascript and xml 异步的javascript和xml技术 二、同步...

  • js的事件循环

    javascript是一个单线程语言,javascript分为同步机制及异步机制,其中同步机制是放在栈中,而异步机...

  • JavaScript本来就很简单(运行机制)

    JavaScript同步与异步 在JavaScript中同步与异步是非常重要的两个概念,首先在这儿做一个总体概述,...

  • javascript 同步异步

    javascript的同步异步和现实生活是相反的。 同步 代码的执行是有顺序的,必须要等前面的执行完成,后面的代码...

  • JavaScript异步编程

    目录 JavaScript采用单线程模式工作的原因 单线程的优势和弊端 同步模式与异步模式同步模式异步模式同步模式...

  • Javascript 异步编程(三)定时器

    Javascript 异步编程(三) 并行?并发?异步? 同步:synchronous: 指所有任务按出现的先后顺...

  • ajax介绍与使用

    一. 什么是ajax asynchronous :异步 synchronous同步 javascript :核心技...

  • ajax

    ajax async javascript and xml在ajax的异步不是我们理解的同步异步编程,而是泛指局部...

网友评论

      本文标题:你不知道的JavaScript 同步异步

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