代码的同步执行和异步执行

Js是一个单线程语言,什么是单线程,一次性只能去办一件事。这个时候如果遇到一个代码需要花很长时间,如定时器,我们是不是要等到定时器执行完成在去执行下面的代码呢,这显然是不可取了,这个时候就出现了执行栈,来存放异步的代码。等主线程把同步的代码执行完成后,在从执行栈中拿异步的代码拿到主线程中执行,这样就很好地解决了Js是单线程的问题。

一.常见的异步任务

定时器,ajax请求,Promise相关等

我们在发送一个请求的时候,需要等服务器响应过来后才去执行Then或者Catch的回调。

如:

我们平常在 

按钮------>调用api方法----------->then(res)=> console.log(res)

按钮------>调用api方法----------->Catch(reject)=> console.log(reject)

这里then拿到的是成功之后的值, Catch拿到的是失败之后的值。

then和Catch是回到函数。

回调函数: 回头在去调用,这里的回头指的是服务器----------->响应---------->客户端。然后去取里面的值。这个过程很显然是一个异步的任务。因为这个过程需要服务器响应给客户端数据。需要一个等待的过程。

我们拿同步任务进行比较:

  console.log(123456)

这个打印可以立马去执行。这就是一个同步任务。

定时器属于不属于异步任务呢?

 setTimeout(() => {
    console.log(123456);
  }, 3000);

这个定时器3秒后才去打印123456。

故也放在执行栈中进行等待,等同步任务执行玩,主线程才去执行中拿出异步任务在去执行。

  console.log(312);
  setTimeout(() => {
    console.log(123456);
  }, 3000);
  console.log(1);

执行的结果大家应该都知道:

312

1

123456

代码:

        setTimeout(function () {
            console.log(1)
        }, 0);
        new Promise(function executor(resolve) {
            console.log(2);
            for (var i = 0; i < 10000; i++) {
                i == 9999 && resolve();
            }
            console.log(3);
        }).then(function () {
 
            console.log(4);
        });
        console.log(5);

代码分析:

 分析
  newPromise里面的任务是同步执行的。
  主线程: console.log(2);
  console.log(3);
  console.log(5);
  for循环肯定执行到9999 返回一个成功的Promise是异步的
  放入执行栈:
    宏:
    setTimeout(function () {
      console.log(1)
    }, 0);
  微:
    resolve().then(function () {
      console.log(4);
    });
  主线程打印 2 3 5
  执行栈拿出任务 到主线程执行
  微 >宏
  打印 4 1
  结果 2, 3, 5, 4 ,1

这里涉及到了微任务中的宏任务>微任务。

二.微任务:微>宏

常见的微任务:

Promise.all, Promise.race Ajax请求等

宏任务:

setimeout等

代码:

 Promise.resolve().then(()=>{
  console.log(123);
 })
 setTimeout(() => {
  console.log(456);
 }, 0);

和循序有关吗?

  setTimeout(() => {
    console.log(456);
  }, 0);
  Promise.resolve().then(() => {
    console.log(123);
  })

可以发现resolve()属于一个微任务。

而且定时器属于宏任务。

结论:

微任务的优先级>宏任务

三.一个长的for循环

for (var i = 0; i < 9999; i++) {
    if (i == 9998) {
      console.log(123);
    }
  }
  console.log(456);

是先执行456 还是执行里面很长的123呢?

 等到for循环才去执行下面代码。

结论:

for循环属于一个同步的任务。

四.习题

  // #1
  setTimeout(() => {

    new Promise(resolve => {
      resolve();
    }).then(() => {
      //  #6
      console.log('test');
    });
    // #5
    console.log(4);
    setTimeout(function () {
      // #8
      Promise.resolve().then(res => {

        console.log(444);
      })
    })
    Promise.resolve().then(res => {
      // #7
      console.log(888);
    })
  });

  // #2
  new Promise(resolve => {
    resolve();
    console.log(1)
  }).then(() => {
    // #3
    console.log(3);
    setTimeout(function () {
      //  #4
      Promise.resolve().then(() => {
        // #7:这一行确确实实打印了 before timeout,但是执行完毕后又产生了一个微任务
        console.log('before timeout'); //#9
        // return Promise.resolve(undefined)
      }).then(() => {

        Promise.resolve().then(() => {
          // #10

          console.log('also before timeout')
        })
      })
    })
  })
  console.log(2);

  // 第一轮: 
  // 主线程: //console.log(1)    console.log(2);
  //   执行栈: //宏:#1 
  //   // 微:#2
  //   第二轮: // 微:#3   //宏:#1  #宏4       console.log(3);
  //   第三轮: // console.log(4);   console.log('test');    console.log(888); 
  //   第四轮: //console.log('before timeout');    console.log('also before timeout')
  //   第五轮: //console.log(444);
  // 结果:1 2  3  4  test   888   before timeout   also before timeout 444

Promise.resolve().then(() => {
     
      Promise.resolve().then(r => {
        
        console.log('a');
        // return Promise.resolve(undefined)
      }).then(r => {
        
        console.log('h');
      }).then(r => {
        
        console.log('8');
      }).then(r => {
        
        console.log('99')
      });
      // return Promise.resolve(undefined)
    }).then(r => {
      
      console.log('44');
    }).then(() => {
      
      console.log('66')
    }).then(() => {
      
      console.log('7')
    })

    // 在执行 Promise.resolve().then的时候同时产生了两个异步任务

    //如果没有返回状态这下一个默认返回一个成功的

    // return Promise.resolve(undefined)

    // 执行的结果: a 44 h  66 8 7 99

 

代码分析:

第一轮:

在执行111的时候产生两个微任务

 

 

这两个先执行第二个。

第二个又是异步 不管。

打印222

然后

打印333

执行444的时候同理

 

 两个异步。执行第二个。

 结果 111  222  333 444  555 666

输出的结果:

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值