【问题标题】:Code not continuing after JavaScript async functionJavaScript异步功能后代码不继续
【发布时间】:2021-07-08 08:09:02
【问题描述】:

我在本地 webapp 上有一个按钮,它调用异步函数来让另一个程序通过 websocket 执行操作。

<button onclick="makeOtherProgramDoThing('arg1','arg2')">

异步函数如下所示:

async function makeOtherProgramDoThing(arg1,arg2){
        let messageCode = sendMessage("someMessageData");  //This sends the message, see info below
        let finalResponse = await receiveFinalResponse(10000,messageCode);
        if(finalResponse[2]=='0'){  // no error
            console.log('no error:'+finalResponse[3]);  //finalResponse[3] is the errorcode
        }else{
            console.log('error:'+finalResponse[3]);
        }
    }
    // Now I update the HMTL to show that it was successful...
}

这个想法是 sendMessage() 将数据发送到我的其他程序,然后回复另一个 .js 文件,该文件有一个名为 lastReceivedMessage 的变量。回到异步函数,在我发送消息后等待recieveFinalResponse(),如下所示。

function receiveFinalResponse(msTimeOut,messageCode){
    return new Promise((resolve,reject) =>{
        var startTime= performance.now();

        while(true){
            if (performance.now()-startTime > msTimeOut){
                reject('Timed Out');
                break;
            }
            if(typeof lastReceivedMessage!== "undefined"){
                if(lastReceivedMessage[1]==='messageCode'){
                    resolve(lastReceivedMessage[0]+";"+lastReceivedMessage[1]+";"+lastReceivedMessage[2]+";"+lastReceivedMessage[3]);
                    break;
                }
            }
        }
    })
}

所以,我希望 receiveFinalResponse() 在超时时间内继续循环并检查与 messageCode 匹配的 lastMessageReceived 的其他 js 文件。

但实际发生的是:sendMessage() 发送消息,然后 receiveFinalMessage() 开始循环,每个循环 lastMessageReceived 都是未知的,直到它超时并经过等待,此时另一个 js 文件最终更新 lastMessageReceived .我以为代码会命中异步函数,开始运行它,然后继续在后台做其他事情,但它似乎只是保持同步并点击 then 函数,正常单步执行,并且只有在它到达其他代码时才到达完成的。是因为我使用了一个while循环来等待响应吗?我怎么能等待响应并冻结一个函数,直到我得到响应,同时让其他代码在后台运行?

提前感谢任何提供帮助的人。

【问题讨论】:

  • 当您运行一个占用线程的紧 while 循环时,不会发生任何其他事情!
  • "所以,我希望 receiveFinalResponse() 继续循环并检查另一个 js 文件"你的循环会阻塞线程,所以你不会收到通知.您的代码只能拒绝承诺。
  • 您明确设置了一个无限的、同步的和牢不可破的while(true) 循环。会出什么问题:)
  • @JeremyThille 我认为它是异步的,我确实提到我认为这可能是问题所在,因为我听说 js 只在一个线程上运行,这让我想知道异步是如何工作的。
  • 嗯,你可以在while循环中有一些异步的东西,但是什么都没有。一切都是同步的。

标签: javascript asynchronous async-await


【解决方案1】:

如果我要将您的代码复制/模拟为一个工作示例,它将如下所示,它确实会重现您的问题。

const delay = ms => new Promise(resolve => setTimeout(resolve,ms));

async function sendMessage(msg){
  await delay(1000);
  window.lastReceivedMessage = ["foo", "messageCode",123456,"abc","def"];
}

function receiveFinalResponse(msTimeOut,messageCode){
    return new Promise((resolve,reject) =>{
        var startTime= performance.now();

        while(true){
            if (performance.now()-startTime > msTimeOut){
                reject('Timed Out');
                break;
            }
            if(typeof lastReceivedMessage!== "undefined"){
                if(lastReceivedMessage[1]==='messageCode'){
                    resolve(lastReceivedMessage[0]+";"+lastReceivedMessage[1]+";"+lastReceivedMessage[2]+";"+lastReceivedMessage[3]);
                    break;
                }
            }
        }
    })
}




(async function(){
    let messageCode = sendMessage("someMessageData");  //This sends the message, see info below
    try{
      let finalResponse = await receiveFinalResponse(10000,messageCode);
      console.log(finalResponse);
    }catch(e){
        console.log(e);
    }
        
})()

请注意,我在那里使用了delay 方法,以便重现sendMessage 函数做一些工作。它应该在 1 秒内完成这项工作,但超时设置为 10 秒,它仍然超时。这是因为您的 while 循环保持线程并且永远不会让步以允许工作完成 - 请记住 javascript 是单线程的。

为了解决这个问题,您需要在您的 while 循环中使用相同的 delay 概念,以便在其他地方产生控制权以完成工作。:

const delay = ms => new Promise(resolve => setTimeout(resolve,ms));

async function sendMessage(msg){
  await delay(1000);
  window.lastReceivedMessage = ["foo", "messageCode",123456,"abc","def"];
}

async function receiveFinalResponse(msTimeOut,messageCode){
    var startTime= performance.now();

    while(true){
        if (performance.now()-startTime > msTimeOut){
            throw('Timed Out');
            break;
        }
        if(typeof lastReceivedMessage!== "undefined"){        
            if(lastReceivedMessage[1]==='messageCode'){
                return lastReceivedMessage[0]+";"+lastReceivedMessage[1]+";"+lastReceivedMessage[2]+";"+lastReceivedMessage[3];
                break;
            }
        }
        await delay(500);
    }
}

(async function(){
    let messageCode = sendMessage("someMessageData");  //This sends the message, see info below
    try{
      let finalResponse = await receiveFinalResponse(10000,messageCode);
      console.log("fr",finalResponse);
    }catch(e){
        console.log("ex",e);
    }
        
})()

旁注:您的意思是if(lastReceivedMessage[1]==='messageCode'){ 实际上是if(lastReceivedMessage[1]===messageCode){?否则,您的函数的第二个参数有些多余。

【讨论】:

  • 谢谢,在循环中添加延迟有效。
猜你喜欢
  • 2019-07-07
  • 2022-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多