JavaScript中是否存在线程不安全的可能性?

时间:2019-03-20 03:11:32

标签: javascript asynchronous concurrency

let arr = [2, 3]

let promiseA = new Promise((resolve)=>{
    // await for io
    resolve(arr.shift())
})
let promiseB = new Promise((resolve)=>{
    // await for io
    resolve(arr.shift())
})
let handler = (data)=>{
    if(!data){
        return console.log("no more")
    }
    console.log(data)
}
promiseA.then(handler)
promiseB.then(handler)

您好,我有一个关于javascript并发的问题。

如果promiseApromiseB会被一个一个地解析,那么就没有问题了。

但是,如果两个io操作花费相同的时间,是否promiseApromiseB都将被值2解析?

1 个答案:

答案 0 :(得分:0)

@Pointy(在评论中)是正确的,但只是为了使其正式化:


承诺正文,消息和事件循环

在两个Promises主体中运行的任何代码都将作为消息在主JavaScript Event Loop中执行。

JavaScript一次运行一条消息,一旦一条消息在主事件循环中运行,它将run to completion发生在其他事情之前:

  

...它不能被抢占,并且可以在其他任何代码运行之前完全运行(并且可以修改函数操作的数据)。

类似setTimeout的调用在主事件循环中排入messages,因此在两个Promises的主体中完成的工作可能跨越多条消息,但是每条消息在一个时间并在完成其他任何操作之前先完成操作。

因此,在每个承诺主体到达此行时:

resolve(arr.shift())

...它将是当前正在运行的消息,并且“不能被抢占,并且将完全在任何其他代码运行之前运行”。


Promise回调和PromiseJobs队列

Promise解析后,等待Promise的所有回调都将在PromiseJobs queue中排队,这是ES6引入的特殊作业队列。

在PromiseJobs队列中的回调在当前消息完成之后,下一条消息开始之前运行,并依次运行一次,直到队列为空。


那么...... promiseA和promiseB是否都将被解析为2?

不。两个Promises都将以值2进行解析的可能性为零。

此行:

resolve(arr.shift())

...是同步的,并且在运行任何其他代码之前,数组操作和resolve都将作为当前运行消息的一部分运行完毕。

这意味着确保每个handler回调都在PromiseJobs中以唯一的值排队。


奖金

保证编写代码的方式handler首先在2中排队在PromiseJobs中,然后再在3之后在PromiseJobs中排队,无论 Promise首先解析,因此保证handler回调按该顺序运行,并且上面的代码将始终打印2,然后再打印3