【问题标题】:Javascript - Handling asynchronous race conditionJavascript - 处理异步竞争条件
【发布时间】:2020-07-12 11:10:53
【问题描述】:

注意在删除之前: 我意识到类似的问题已经被问过很多次了,但是我花了几个小时尝试使用其他人的回复来实现这个,最近是来自 noseratio 在这个线程Proper way to wait for one function to finish before continuing? 中的回复并且没有成功。


我有一个 nodeJS 服务器,它在我的函数 f1 请求它时成功返回数据,另一个函数 f2 调用 f1 然后打算对这个异步函数的输出做一些事情。我正在尝试使用 async/await 语法和 f2 中的附加承诺来做到这一点,如下所示。

async function f1(){
   try{
       let response = await fetch('MY SERVER URL');
       let data = await response.json();
       return await data;
   }
   catch(e) {
       alert(e);
   }
};


function f2() {
    var promise = f1();
    promise.then(function(result) {
        JSONdata = promise.markers;
        console.log("JSON read into f2");
    })    

    console.log(JSONdata);

然后 f2 继续做其他事情......

但问题是我遇到了竞态条件,结果 f1 没有及时返回,无法对其进行任何操作,因此变量未定义。

任何关于如何减轻这种情况的帮助将不胜感激,谢谢。

【问题讨论】:

  • 三重 await 应该在 f1 中出错,你不应该需要最后一个 await。这也不是竞争条件,所有依赖于被解决的承诺的东西都应该放在then 语句中,或者你可以使用另一个async 函数。
  • @Aplet123 我基本同意,但是最后一个await 不应该出错。它不是必需的,但等待非承诺返回值本身。 n = await 1 将简单地将1 分配给n
  • 嗯,这很奇怪。我一直养成了不等待非承诺的习惯。
  • 嗯,console.log(JSONdata); 应该在 then......
  • 请发布“然后 f2 继续做其他事情...”的确切代码。一般来说,没有办法避免将这些东西放在then 回调中或await 之后,并让f2 也返回一个承诺。这就是 f1 是异步的意思。

标签: javascript async-await es6-promise


【解决方案1】:

坚持这种模式。

async func1() { 
  console.log('this is async function')
  return JSON.parse(await fetch(options))
}

func2 () { 
   console.log('this is not async function')
 }

        if(await func1()){
            func2()
        }

而且你在函数 1 中有太多的等待。只等待承诺的返回。 而且你不应该在这个级别上混淆'.then'和'await'语法。尝试坚持一种模式,然后探索另一种模式。然后混合它。

【讨论】:

    【解决方案2】:

    这样的事情应该可以工作:

    async function f1() {
       try {
           const response = await fetch('MY SERVER URL')
           return await response.json()
       } catch(e) {
           console.error(e)
       }
    }
    
    async function f2() {
        const { markers } = await f1()
        console.log(`Result supplied to 'f2': ${markers}`)
    }
    

    在您的代码中,return await data 中的 await 是多余的,因为 data 不是承诺;此外,f2 似乎不完整。

    请注意,虽然在一般情况下,return await...async 函数中是不必要的(并且被认为是错误的形式,即使它是无害的),如果你想要一个周围的 try...catch 来捕捉承诺拒绝,那么 @ 987654329@ 是必要的。见here

    【讨论】:

    • 实际上,try 块是唯一一个await不是冗余的地方。 (多余的是data上的第二个await
    • 哦,好的。那么利用f1中的catch,return await是否有效?
    【解决方案3】:

    您应该在then 回调中移动使用f1 结果的逻辑。

    function f2() {
        var promise = f1();
        promise.then(function(result) {
            var JSONdata = result.markers;
            console.log("JSON read into f2");
    
            console.log(JSONdata);
        });
    }
    

    或将f2 更改为async function,以便await 返回值。

    async function f2() {
        var result = await f1();
        var JSONdata = result.markers;
        console.log("JSON read into f2");
    
        console.log(JSONdata);
    }
    

    如果您还没有,请查看MDN Using Promises 指南,该指南对它们进行了非常详尽的解释。当你了解了 Promise 的工作原理后,async/await 也会变得更容易理解。

    【讨论】:

    • 完美,非常感谢。我将再次阅读那些 MDN 文档 - 我现在意识到我已经混淆了多种语法和句法糖化的变体。
    猜你喜欢
    • 2010-11-27
    • 2012-01-26
    • 2014-02-23
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多