【问题标题】:How to make parts of a code wait until another part has completed using async-await如何使用 async-await 使部分代码等到另一部分完成
【发布时间】:2021-04-10 01:15:55
【问题描述】:

我需要先完成部分函数调用,然后再恢复其余部分。目标是我需要注册/记录流程的第一部分运行多长时间以用于报告目的。

在下面的代码中,第一个var data 使用输入参数X2,Y2,Z2 运行以在数据库中查找相应的值。 var api 自动触发并记录开始时间。

然后我需要var data 来完成,然后运行var api2,这将注册一个完成时间。这将在可接受的准确度范围内为我提供“var 数据”的大致运行时间。

有人知道我该怎么做吗?

function Searh_09() {
   var data = {
     'X': document.id('X2').value,
     'Y': document.id('Y2').value,
     'Z': document.id('Z2').value,
     'Transform': 'Templates/Report/Standard.xslt'
   }; 

   if (!X)
      return;

   if (!Y)
      return;

   if (!Z)
       return;

   var api = new qbo3.ProcessObject();
   api.invokeJson('StartTime',data);

   var api2 = new qbo3.ProcessObject();
   api2.invokeJson('EndTime');
}

【问题讨论】:

  • 什么是qbo3.ProcessObjectinvokeJson() 方法有什么作用?如果是异步的,是返回 Promise 还是接受回调?
  • @David qbo3.ProcessObject 将 StartTime 和 EndTime 声明为 Web 应用程序 (QBO) 中的对象以供内部使用。 invokeJson 用于启用 Json 跨服务器转换数据的使用...这是我最好的理解,Web 应用程序 QBO 最近已经实现,并结合了很多高级编码“引擎盖下”我无法访问。
  • @T8100:您将需要了解这些对象/方法如何执行其异步操作的细节。一般来说,这样的方法要么接受回调,要么返回 Promise。使用这些信息,您可以构建代码以在执行下一个操作之前等待该操作。
  • @KooiInc 我很抱歉,但以上是我能做的最好的......“qbo3.ProcessObject 将 StartTime 和 EndTime 声明为 Web 应用程序 (QBO) 中的对象以供内部使用。invokeJson 是用于启用 Json 跨服务器转换数据的使用..."

标签: javascript async-await promise


【解决方案1】:
cmets 中的

A link you provided 提供了对 invokeJson 操作的一些洞察。特别是这里的这一点:

invokeJson(method, data, { success: resolve, error: reject })

第三个方法参数上的 successerror 属性是回调。与常见的 jQuery AJAX 实现类似,它们本质上是您创建函数的地方,这些函数将在稍后操作完成(或失败)时调用。

由于您的代码调用了其中的 2 个操作,因此您实际上可以调试三个“时刻”。第一次手术前,两次手术之间,第二次手术后。使用您拥有的工具可能看起来像这样:

console.log('Before first operation.');
var api = new qbo3.ProcessObject();
api.invokeJson('StartTime', data, {
  success: function () {
    console.log('Between the operations.');
    var api2 = new qbo3.ProcessObject();
    api2.invokeJson('EndTime', null, {
      success: function () {
        console.log('After second operation.');
      }
    });
  }
});

如您所见,对invokeJson() 的每次调用都包含一个带有success 回调函数的第三个参数,该回调函数将在异步操作完成后调用。


现在,针对您的问题,具体来说:

如何使部分代码等待另一部分完成使用异步等待

您使用的库似乎没有使用 async/await。但是,cmets 中的the answer you linked to 显示了如何解决这个问题。您可以将操作包装在 Promise 中,其结构包括 resolvereject 函数,它们完全完成 successerror 回调的作用。

稍微修改该答案中的代码,您可以创建一个函数,该函数接受您的api 对象之一并返回invokeJson 周围的承诺。也许是这样的:

async function invokeJsonAsync(api, str, data) {
  return new Promise(function (resolve, reject) {
    api.invokeJson(str, data, { success: resolve, error: reject });
  });
}

现在,您无需直接在 api 对象上调用 invokeJson,而是将它们传递给此函数,并将 await 返回的 Promise

var api = new qbo3.ProcessObject();
await invokeJsonAsync(api, 'StartTime', data);

var api2 = new qbo3.ProcessObject();
await invokeJsonAsync(api2, 'EndTime');

请注意,您还需要在 Searh_09 函数定义中使用 async 关键字才能在该函数中使用 await

链接的答案更进一步,将此函数作为api 对象本身的一部分。如果您希望经常使用它,那会更干净。程序员似乎这样做是为了使用.then() 将这些调用链接在一起。使用 await 具有相同的效果,并且正是您所要求的。


总的来说,值得理解的是,这并不是“让部分代码等到其他部分完成”。默认情况下,代码会这样做。它强制逐行执行,直到完成。

然而,目前一些代码调用的操作是异步。这意味着执行该操作的上下文被卸载到正在运行的代码之外的另一个进程。正在运行的代码将继续执行更多语句。稍后,当该异步过程完成时,它会将控制权转移回此代码以进行任何可能的后续操作。

由于 JavaScript 是单线程的,因此对这些异步操作的任何后续操作都将在所有命令式代码语句都执行后发生。后来被调用的后续操作就是这些回调函数。 (因此得名...它是一个函数,当控件返回给代码时会被调用。另一个进程正在使用这个函数来“回调我们”。)

asyncawait 只需将其包装成更简洁的语法。但最终“等待”的是具有回调函数的Promise。当您使用await 时,您基本上是在告诉代码当前函数中此语句之后的所有内容都是回调。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    相关资源
    最近更新 更多