使用Promise调用函数在循环中挂起

时间:2017-08-15 13:33:38

标签: javascript promise

运行以下javascript代码时,它可以正常工作。但是如果你删除了setTimeout函数调用并用一行代码替换它,如:

resolve(x);

浏览器将挂起。

浏览器似乎挂起,因为它正在处理无限循环中对processNode函数的调用。但是,目前还不清楚为什么会发生阻塞。 processNode返回一个Promise。此外,startNodeProcessing是一个异步函数,它在调用时使用await。我认为通过使用等待的Promise和async函数可以防止任何阻塞线程,但显然我错了。似乎setTimeout只是在一个单独的线程上执行其代码,从而阻止了阻塞。但如果是这种情况,为什么还要使用Promise或async函数来开始?

function processNode(x) {
    return new Promise(resolve => {
        console.log("X: " + x + "  " + Date.now());
        setTimeout(() => {
            resolve(x);
        }, x);
    });
}

async function startNodeProcessing() {
    while(true) {
        var a = processNode(1);
        var b = processNode(1);
        var c = processNode(1);
        var d = processNode(1);
        var a1 = await a;
        var b1 = await b;
        var c1 = await c;
        var d1 = await d;
    }

    return;
}

startNodeProcessing();

2 个答案:

答案 0 :(得分:1)

以下情况发生了:

 var a = processNode(1);
//the parser jumps to processNode and creates a promise:
return new Promise(function(resolve)
//the promise is resolved
resolve(x);
//the function returns, we enter the main function again:       
var a1 = await a;
//await internally calls the then function:
a1.then(return to this func)
//as the promise is resolved, the then callback is called immeadiately
//the parser returns to the main function

正如您所看到的,解析器永远不会退出循环,因此它会阻塞,因为它永远不会停止。

答案 1 :(得分:0)

  

此外,startNodeProcessing是一个异步函数   在电话上使用等待。

不,await未在通话中使用。调用是在await之前的行进行的。见serial await requests in a return run in parallel?

  

它在没有setTimeout的情况下阻塞。只需将setTimeout替换为   resolve(x)它会阻塞。我试图了解原因。

因为立即调用了Promise构造函数executor函数,所以立即调用Question中console.log()构造函数中的Promise,无论是否或何时{{1函数参数被调用。

resolve

Promise

  

语法

     

Promise(resolve => { console.log("this is not executed asynchrously"); resolve(1) })

     

参数

     

执行

     

使用参数resolve和reject传递的函数。该   执行函数由Promise立即执行   实现,传递解析和拒绝功能(执行者是   在Promise构造函数之前调用甚至返回创建的   对象)。