首页 > 解决方案 > 如何使用 async-await 使部分代码等到另一部分完成

问题描述

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

在下面的代码中,第一次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');
}

标签: javascriptasync-awaitpromise

解决方案


您在评论中提供的链接提供了对此操作的一些见解。invokeJson特别是这里的这一点:

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

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

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

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使部分代码等到另一部分完成

您正在使用的库似乎没有使用 async/await。但是,您在评论中链接的答案显示了如何解决这个问题。您可以将操作包装在 a 中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 });
  });
}

现在不是invokeJson直接调用你的api对象,而是将它们传递给这个函数并await返回Promise

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

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

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

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


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

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

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

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


推荐阅读