LabVIEW Web Development Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Request for Feedback - Promise/async/await Example

Solved!
Go to solution

Hi, I'm creating a training slide of LabVIEW NXG Web Module. I would like to introduce promise/async/await on the slide but I don't have much javascript skill so I hope someone give me a feedback for my example.

Of course I know there is a good example code on help page but I'm trying to create my original example.

Waiting for Asynchronous JavaScript Operations to Complete in a Web Application

 

Does this scenario have wrong or insufficient points?

Can I improve my example?

Because this slide is for LabVIEW beginners, the example must be simple.

 

The scenario is,

  1. My code doesn't work what I expected...
  2. Try promise/async/await!! They resolve the issue.

Step1

(function () {
    'use strict';   
   /*FunctionA Timer*/
    window.MyTimer = function (waitCount) {
       for(var i=0; i<waitCount; i++){}
    };

   /*divide*/
    window.MyDivide = function (num, den) {
    return num/den;
    };

}());

step1.pngAt this step, divide loop doesn't run fast. The loop rate is affected by MyTimer.

 

Step2

Let's try promise/async/await. A loop rate of MyDivide isn't affected by MyTimer.

(function () {
    'use strict';
    /**/
    const sleep = function (time) {
        return new Promise(function (resolve) {
            setTimeout(resolve, time);
        });
    };

    window.MyTimer = async function (waitCount) {
       await sleep(waitCount);
    };

    window.MyDivide = function (num, den) {
    return num/den;
    };

}());

 

Certified LabVIEW Developer
There are only two ways to tell somebody thanks: Kudos and Marked Solutions

GCentral
0 Kudos
Message 1 of 5
(4,296 Views)

Hi Emboar,

 

Your example does show the syntax well. One perspective that may help clarify the goal is focusing on the use case of "how do I wait for a JavaScript function with a callback to finish?"

 

Lets say you want to wait for the setTimeout function to complete, you may try something like the following:

(function () {
    'use strict';

    window.WaitWithoutPromise = function () {
        setTimeout(function () {
            console.log('finished!');
        }, 1000);
    };
}());

 

But running the WebVI you notice that the WaitWithoutPromise function does not wait for the timer to finish:

MilanR_0-1576444686867.png

 

MilanR_2-1576444725355.png

 

Instead we can use an async function (or a normal function that returns a Promise) and when the WebVI invokes the function it knows to wait until the Promise completes before continuing.

 

(function () {
    'use strict';

    const sleep = function (time) {
        return new Promise(function (resolve) {
            setTimeout(resolve, time);
        });
    };

    window.WaitWithPromise = async function () {
        await sleep(1000);
    };
}());

 

 

MilanR_3-1576445035131.png

 

MilanR_4-1576445062780.png

By wrapping the callback based function to instead be Promise based we were able to get the WebVI to wait for the functions completion before continuing. I attached the above example in-case it is useful.


Milan
Message 2 of 5
(3,826 Views)

Hi MilanR, I really appreciate your kind reply. I will use both examples in my training slide.

I'd like to explain well why LabVIEW doesn't defer the execution with setTimeout function.

 

In general, Javascript doesn't have sleep function so when we want to defer an execution, we can use

  • Busy wait (my example)
  • setTimeout (your example)
  • setInterval
  • etc...

I cannot explain well why setTimeout doesn't work what we expected in LabVIEW.

Is this a special for LabVIEW or general thought in Javacript?

Certified LabVIEW Developer
There are only two ways to tell somebody thanks: Kudos and Marked Solutions

GCentral
0 Kudos
Message 3 of 5
(3,817 Views)
Solution
Accepted by Tepig

Hi Emboar,

 


I cannot explain well why setTimeout doesn't work what we expected in LabVIEW.

Is this a special for LabVIEW or general thought in Javacript?


Requiring a callback for long running tasks is a general case in JavaScript. The JavaScript language is single threaded so we cannot have blocking operations like busy-wait loops. If your busy-wait loop lasted a couple of seconds, the browser would actually show a dialog saying the page is unresponsive and stop your script. In addition, while a busy-wait loop is running in JavaScript other page actions like button clicks and scrolling will be blocked; the page appears hung when using a busy-wait loop.

 

You should not use busy-wait loops in JavaScript at all and instead you will notice that most JavaScript APIs for long running tasks are callback-based or Promise-based. That includes the setTimeout function which is a callback-based version of sleep.

 

When you run JavaScript like the following:

console.log('first');
setTimeout(function callback () {
    console.log('third');
}, 1000);
console.log('second');

 

You will notice that the print order is "first", "second", "third". In this case (just like in the LabVIEW case) the setTimeout function is called and then immediately the following console.log('second'); line is called. JavaScript did not halt execution to wait for the setTimeout to finish. It's only after this JavaScript callstack has finished that a new JavaScript callstack will be made one second in the future that will call the callback function.

 

With WebVIs the way to signal to the WebVI runtime that it has to wait is to use a Promise which is an object that tracks the execution of a task. An alternate version of the example I gave that shows this more explicitly is the following:

window.WaitWithPromise = function () {
    // Create a Promise to keep track of task execution
    let myResolve;
    let myPromise = new Promise(function (resolve) {
        myResolve = resolve;
    });
    
    // Create a long running task
    setTimeout(function callback () {
        // In the callback, run the resolve function created by the Promise so
        // the Promise knows the task is complete
        myResolve();
    }, 1000);
    
    // Return the Promise so LabVIEW can keep track of the execution
    // LabVIEW will wait for the Promise to finish which happens when myResolve is called
    return myPromise;
};

The above example breaks down the creation of a Promise object, attaching that Promise to a callback, and returning the Promise object so LabVIEW can use it to keep track of when the callback has run and the long-running task has finished.

 

In summary:

 

JavaScript callback and Promise behavior is a general feature and does make for trickier coding. In general we handle all that under the hood for WebVIs, you can use multiple parallel busy-wait while loops on a LabVIEW diagram with no issue and the runtime will make sure pages stay interactive with scrolling and button clicks, etc.

 

When using the JSLI document you do need to be aware of how to use Promises when calling JavaScript APIs that use callbacks or Promises to signal when a task is complete.


Milan
Message 4 of 5
(3,807 Views)

I clearly understood what does Javascript do. I really appreciate your kind effort.

I'll update and publish my slide on web, share the url later.

Certified LabVIEW Developer
There are only two ways to tell somebody thanks: Kudos and Marked Solutions

GCentral
Message 5 of 5
(3,793 Views)