当前位置: 首页 > 知识库问答 >
问题:

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

井翰
2024-09-29

关于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),请问程序是自动结束了还是阻塞中?

共有3个答案

戴高远
2024-09-29

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

陈飞
2024-09-29

首先分环境说这个问题

  • 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

顾梓
2024-09-29

在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等方法来避免无限期的等待。
 类似资料:
  • 问题内容: Java文档说“同一对象上的同步方法的两次调用不可能交错”。我需要知道的是,synchronized是否还会阻止 同一类的 两个不同 实例中的 同步方法交织。 例如,类Worker具有称为process()的方法。我们有几个在自己的线程中运行的Worker实例。我们希望防止多个实例同时运行process()方法。会 同步 吗? 谢谢。 问题答案: 没有; 仅防止多个线程在 同一 实例中

  • 以下代码在 chrome 输出 1,2,3 这个在网上找到了,forEach 一开始就已经获取了 数组长度 The range of elements processed by forEach is set before the first call to callbackfn. Elements which are appended to the array after the call to

  • 问题内容: 首先,这是一个非常特殊的情况,它以错误的方式故意将异步调用改型为一个非常同步的代码库,该代码库长成千上万行,并且当前时间不具备进行更改的能力。对的。” 它伤害了我的每一个生命,但是现实和理想往往并没有相互融合。我知道这很糟糕。 好的,顺便说一句,我该如何做,这样我可以: 示例(或缺少示例)全部使用库和/或编译器,这两种库均不适用于此解决方案。我需要一个如何使其冻结的具体示例(例如,在调

  • 问题内容: 我对诺言有很多困惑。是同步还是异步? 问题答案: 传递函数 为 无极构造同步运行,但任何依赖于它的分辨率将异步调用。即使promise立即解决,任何处理程序都将异步执行(类似于when )-主线程首先运行到末尾。 不管您的Javascript环境如何,都是如此-无论您是在Node还是浏览器中。

  • 我有一个需要在循环中执行的请求promise,比如: 问题是我永远不知道数组中有多少元素,所以我需要一个动态模式。有没有可能混合同步和异步世界,以便在一个时刻只有一个请求是活动的(序列不重要)?

  • 问题内容: 我有一个纯JavaScript Promise(内置实现或poly-fill): 根据规范,Promise可以是以下之一: “解决”和“解决” “解决”和“拒绝” “待定” 我有一个用例,希望同步查询Promise并确定: 承诺解决了吗? 如果是这样,承诺是否得到解决? 我知道我可以用来安排Promise更改状态后异步执行的工作。我不是问怎么做。 这个问题具体是关于 对Promise状

  • 我有一个vue写的标签 其中,queryByPrimaryKey返回的是一个promise,所以这里用await等待promise的值,因为用到了await,所以外层又需要用async包裹,这样整体函数返回的又是一个promise,那么src属性实际上要的是返回的string值,而不是包裹着string的promise,我如何拿到string值?

  • 背景:基于Element UI 开发的项目,使用到了Tree树型控件 需求:页面有一个tree控件(可选择)如图 这个控件在切换月份的时候可能存在二级节点下有新增的节点或者减少的节点, 如果 ‘一级2’被全部中了,那么切换其他月份如果 ‘一级2’节点下有新增的节点也要勾选上。 树的深度不确定(后端返的),数据量大的时候遍历判断会影响性能,求问各位大佬 有什么比较好的办法处理吗 找出两颗树的差异的节