关于JS的Promise同步调用问题?

关于JS的Promise同步调用问题

async function yyy() {
    console.log('yyy调用xxx开始')
    let res = await xxx()
    console.log('yyy调用xxx结束', res)
},            
async function xxx() {
    return new Promise(function(resolve, reject) {

    })
}

请问函数 xxx 中没有调用 resolve,也没有调用 reject,那么 yyy 函数运行到 await xxx () 是结束运行还是在一直阻塞?

并没有执行console.log('yyy调用xxx结束', res),请问程序是自动结束了还是阻塞中?

阅读 1.1k
avatarAI BotBETA

在JavaScript中,当使用async/awaitPromise时,如果Promise没有被解决(即没有调用resolvereject),那么await调用将会持续等待,直到Promise被解决或拒绝。在你给出的代码示例中,xxx函数创建了一个Promise但从未解决它,因此yyy函数在await xxx()处会一直处于阻塞状态。

async function yyy() {
    console.log('yyy调用xxx开始')
    let res = await xxx() // 这里会阻塞,因为xxx的Promise从未被解决
    console.log('yyy调用xxx结束', res) // 这行代码不会被执行
}

async function xxx() {
    return new Promise(function(resolve, reject) {
        // 没有调用 resolve 或 reject,因此Promise永远不会解决
    })
}

解释

  • yyy函数执行到await xxx()时,它会在那里暂停执行,并等待xxx函数返回的Promise被解决。
  • 然而,由于xxx函数中的Promise既没有调用resolve也没有调用reject,这个Promise将永远不会被解决,因此await调用将无限期地等待。
  • 这种情况下,console.log('yyy调用xxx结束', res)这行代码将永远不会被执行,因为程序在等待Promise解决时被阻塞了。
  • 如果你的JavaScript环境(如浏览器或Node.js)没有设置超时或类似的机制来自动终止这种无限等待的情况,那么程序将无限期地挂起在那里。

注意

  • 在实际应用中,确保你的Promise总是被适当地解决或拒绝是非常重要的,以避免程序出现意外的阻塞或挂起。
  • 你可以通过添加适当的超时机制或使用Promise.race等方法来避免无限期的等待。
2 个回答
✓ 已被采纳

首先分环境说这个问题

  • Node
    返回的Promise没有被resolvereject,导致它永远处于pending状态。但是,由于没有其他活动的异步操作(例如定时器、网络请求等),Node.js 的事件循环会发现没有任何待处理的任务或微任务,因此它会认为程序已经完成并退出。

Node.js的事件循环会持续运行,直到所有的异步操作都完成并且没有更多的回调函数需要执行。如果一个Promise保持pending状态,而没有其他活跃的操作,那么事件循环将不会等待这个Promise完成,而是直接结束进程。
image.png

  • 在浏览器下

await将会一直等待这个Promise完成。由于没有其他活动的异步操作来保持事件循环忙碌,浏览器环境中的 JavaScript引擎可能会认为脚本已经执行完毕,并且如果这是页面加载过程中的一部分,它可能不会阻止整个页面的渲染或交互。

然而,如果你在一个独立的脚本中(比如直接在<script>标签内或者通过控制台输入),并且这个脚本是同步执行的,那么一旦执行到await xxx()并且xxx返回的Promise没有被resolvereject, 浏览器将不会继续执行后面的代码。但是,这并不意味着浏览器会完全阻塞。用户仍然可以与页面进行交互,只是你的脚本的剩余部分不会被执行。
image.png

把你的代码换成

async function yyy() {
    console.log('yyy调用xxx开始')
    let res = await xxx()
    console.log('yyy调用xxx结束', res)
}

async function xxx() {
    return new Promise(function(resolve, reject) {
        let time = new Date().getTime();
        while(1) {
            let current = new Date().getTime();;
            if(current - time > 1000){
                console.log('xxx running ...');
                time = new Date().getTime();
            }
        }
    })
}

yyy();

你将看到yyy持续的阻塞,xxx在后台运行
image.png

它应该是被阻塞的,因为 await 是会阻止后续代码的执行,直到 await 执行的函数执行完毕,但是await 的函数没有正确执行完,所以它一直都在等待状态,也就不会打印console.log('yyy调用xxx结束', res) 了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏