JS运行机制

JS为一门单线程语言;JS的执行机制是Event Loop事件循环

JS单线程,就是按语句出现顺序执行--等待前一个任务的结束,再去执行下一个任务,称为JS执行的主线程。

普通的JS任务按语句的出现顺序,在主线程上执行,这类任务称为同步任务;但是对于执行时间很长的任务(类似于Ajax请求),就会阻塞代码的执行,为避免此情况的产生,可以先将该类任务挂起,这类任务称为异步任务。

首先放个初级代码

// code1
console.log('1')

setTimeout(function() {
    console.log('2')
}, 0)

console.log('3')

从理论上总结JS的执行机制:
(1)同步和异步任务进入不同的执行线,同步任务直接按顺序进入主线程,异步任务进入到Event Table中并注册对应的回调函数
(2)指定的事情完成时,Event Table会将函数移入事件队列(Event Queue)中
(3)主线程任务执行,执行完毕后,读取事件队列函数到主线程中并执行
(4)JS事件循环,不断执行上述操作

上面code1的输出结果为:1,3,2。注意code1中setTimeout的延迟为0毫秒,但是并没有立即执行,仍然在最后输出,即为异步任务。

更新代码段

// code2
setTimeout(function() {
    console.log('2')
}, 2000)

sleep(5000)

// 5秒后输出‘2’
// 尽管延迟了3秒,但是主线程的执行花了5秒钟
// 开始时console被注册到Event Table,开始计时;3秒的时候console进入到事件队列;5秒的时候console进入到主线程

插入总结一下JS中的同步任务异步任务有哪些

异步任务:ajax请求、事件绑定、定时器、new Promise的回调(then、catch)以及其他一些回调函数
同步任务:new Promise构造函数、其它script 语句

对任务进行更细致的划分,分为宏任务微任务,其中

宏任务:包括整体代码script,setTimeout,setInterval
微任务:Promise,Node.js的process.nextTick

重新描述JS的执行过程:
整体代码为宏任务,开始第一次事件循环,执行完宏任务后执行微任务,结束第一次事件循环;开始第二次循环,看执行宏任务,再执行微任务,结束第二次循环。不断重复循环上述执行。

接下来以promise为例,更新代码

// code3
setTimeout(function() {
    console.log('1');
}, 0)

new Promise(function(resolve) {
    console.log('2');
}).then(function() {
    console.log('3');
})

console.log('4');

执行过程:

  1. 整段代码进入到主线程
  2. setTimeout 回调被注册进入Event Table,而后进入Event Queue
  3. Promise构造函数立即执行,console语句输出2,then回调进入到微任务的Event Queue中
  4. console语句立即执行,输出4
  5. 此时第一次循环的宏任务执行完毕,开始执行第一次循环里面的微任务,输出promise的then回调里面的console,输出3
  6. 结束第一次循环,开始第二次循环,执行宏任务setTimeout,输出1

附上找来的一个总结性例子

// process.nextTick方法可以在当前"执行栈"的尾部----
// 下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。
// 也就是说,它指定的任务总是发生在所有异步任务之前

// code4, 输出结果再文末
console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})

process.nextTick(function() {
    console.log('6');
})

new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

最后,附上爬这篇总结的导火代码:

testFunction() {
    // ...
    this.intershipList[index].logDetail = this.getgetLogDetail(index, id)
    this.intershipList.splice(this.intershipList, 0)
    /* this.getLogDetail(index, id) */
    // ...
},

getLogDetail(index, id) {
    // ...
    this.$axios
      .post('***', postData)
      .then(response => {
        if (response.success) {
          return response.data;
        } else {
          return []
        }
        /* if (response.success) {
              this.intershipList[index].logDetail = response.data
              this.intershipList.splice(this.intershipList, 0)
           } */
      })
      .catch(err => {
        console.log(err)
      })
}

现在再来看,就很清楚的明白为什么intershipList的数据没能更新啦。另外,上述代码中使用数组的splice操作方法,更新视图,参考vue数据更新,视图无法更新问题 。

// code4输出结果
// 1 7 6 8 2 4 3 5 9 11 10 12

你可能感兴趣的:(JS运行机制)