0

I need to have a part of a function call be completed first and then the rest of it to resume. The goal is that I need to register/record how long the first part of the process runs for reporting purposes.

In the code below, the first var data run using input parameters X2,Y2,Z2 to find corresponding values in a database. var api is triggered automatically and records a start time.

I then need var data to complete and then run var api2 which will register a completion time. This will give me the approximate run time for “var data” within acceptable levels of accuracy.

Does anyone know how I could do this?

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');
}
Sandeep Ranjan
  • 824
  • 15
  • 33
T8100
  • 13
  • 4
  • 1
    What is `qbo3.ProcessObject`? What does the `invokeJson()` method do? If it's asynchronous, does it return a Promise or accept a callback? – David Apr 05 '21 at 14:18
  • 1
    Please try to provide a [minimal reproducable example](https://stackoverflow.com/help/minimal-reproducible-example) – KooiInc Apr 05 '21 at 14:21
  • @David qbo3.ProcessObject is declaring StartTime and EndTime as objects in a web application (QBO) for use internally. The invokeJson is used to enable the use of Json in translating data across a server... This is my best understanding, the web application QBO has been recently implemented and combines a lot of high level coding "beneath the hood" that I'm not able to access. – T8100 Apr 05 '21 at 14:59
  • @T8100: You're going to need to know the specifics about how these objects/methods perform their asynchronous operations. In general such a method would either accept a callback or return a Promise. With that information you can structure your code to await that operation before performing the next operation. – David Apr 05 '21 at 15:13
  • @KooiInc I'm sorry but above is the best I can do..."qbo3.ProcessObject is declaring StartTime and EndTime as objects in a web application (QBO) for use internally. The invokeJson is used to enable the use of Json in translating data across a server..." – T8100 Apr 05 '21 at 15:46
  • @David here's an explanation of the QBO stuff, I'm still not getting it though, any ideas? https://stackoverflow.com/questions/66994800/qbo3-javascript-promises/66994801#66994801 – T8100 Apr 09 '21 at 14:33
  • @KooiInc here's an explanation of the QBO stuff, I'm still not getting it though, any ideas? https://stackoverflow.com/questions/66994800/qbo3-javascript-promises/66994801#66994801 – T8100 Apr 09 '21 at 14:34
  • @T8100: That doesn't go into much detail, but from the syntax used on the answer it appears that `invokeJson()` accepts a third parameter which is an object containing a variety of properties, two of which are `success` and `error` callback functions which would be invoked at a later time depending on the completion of failure of the `invokeJson` operation. Anything you want to happen after the operation completes would need to go in those functions. (Or for a more elegant Promise-based approach, that answer shows how to wrap `invokeJson` in a Promise.) – David Apr 09 '21 at 14:37

1 Answers1

0

A link you provided in comments offers some insight into this invokeJson operation. Specifically this bit here:

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

Those success and error properties on that third method parameter are callbacks. Similar to the often seen jQuery AJAX implementation, they essentially are where you would create functions that will be invoked at a later time when the operation finishes (or fails).

Since your code is invoking 2 of these operations, you effectively have three "moments" you can debug. Before the first operation, between the two operations, and after the second operation. Using the tools you have that might look something like this:

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.');
      }
    });
  }
});

As you can see, each call to invokeJson() includes a third parameter with a success callback function, which will be invoked after the asynchronous operation completes.


Now, to your question, specifically:

How to make parts of a code wait until another part has completed using async-await

The library you're using doesn't seem to make use of async/await. However, the answer you linked to in comments shows how to get around that. You'd wrap the operation in a Promise, the structure of which includes resolve and reject functions which do exactly what the success and error callbacks do.

Slightly modifying the code in that answer, you can create a function which accepts one of your api objects and returns a promise around invokeJson. Perhaps something like this:

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

Now instead of calling invokeJson directly on your api objects, you'd pass them to this function and await the returned Promise:

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

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

Note that you'd also need to use the async keyword on your Searh_09 function definition in order to use await within that function.

The linked answer takes it a step further by making this function part of the api objects themselves. Which would be cleaner if you expect to use this a lot. The programmer appears to have done that with the intent of using .then() to chain these calls together. Using await has the same effect, and is specifically what you were asking for.


Overall, it's worth understanding that this isn't "making parts of the code wait until other parts complete". Code does that by default. It imperatively executes line by line until it completes.

However, some of the operations invoked by code these days are asynchronous. Which means the context of performing that operation is offloaded to another process outside of the code that's running. The code that's running will continue to execute more statements. At a later time, when that asynchronous process completes, it will transfer control back to this code for any potential follow-up.

Since JavaScript is single-threaded, any follow-ups to these asynchronous operations will happen after all of the imperative code statements have been executed. The follow-up operations which later get invoked are these callback functions. (Hence the name... It's a function that will be invoked when the control is returned to the code. The other process is using this function to "call us back".)

async and await simply wrap this in cleaner syntax. But ultimately what's being "awaited" is a Promise which has callback functions. When you use await you're basically telling the code that everything after this statement in the current function is the callback.

David
  • 208,112
  • 36
  • 198
  • 279