Skip to Content
Technical Articles

Learn JavaScript as ABAP developer Part 3

  1. Variable declaration
  2. Function declaration
  3. Concurrency with Promises and async functions
  4. Encapsulation with modules
  5. Scripting in UI5 applications

Introduction

In this blog series i want to show you from the perspective of an ABAP developer the basics of JavaScript. Both languages have in some way familiar concepts.

Concurrency

Concurrency can be implemented in the ABAP universe with asynchronous remote function calls (RFC).

In JavaScript we can achieve the same behavior with Promises or async-functions.

Promises

A simple promise is created in the following listing.


const helloWorldPromise = new Promise(function(resolve, reject){
  setTimeout(() => console.log('Hello World', 1000);
});
console.log('Wait for my first promise!');

When you run this program, you can recognize first ‘Wait for my first promise!’ is printed and after one second, ‘Hello World’ is printed. You can compare this promise to the following simple ABAP program:


FUNCTION ZHELLO_WORLD.
  WAIT UP TO 1 SECONDS.
  WRITE 'Hello World'. NEW-LINE.
ENDFUNCTION.

CALL FUNCTION 'ZHELLO_WORLD'
  STARTING NEW TASK 'task_1'.
WRITE 'Waiting for my first asynchronous function'.

Promises can be fulfilled or rejected. Callbacks for fulfilled or rejected promises should be attached.


const fulFilledPromise = new Promise(function(resolve, reject){
  setTimeout(() => resolve({message: 'task successful', type: 'S'}), 1000);
}).then(function(result){
  console.log(result);
});
const rejectedPromise = new Promise(function(resolve, reject){
  setTimeout(() => reject(new Error('validation error')), 2000);
}).catch(function(reason){
   console.log(reason);
});

The callback for the fulFilledPromise logs the object ‘{message: ‘task successful’, type: ‘S’}’, which was passed to the resolve-function. The callback for the rejectedPromise logs a error, which was passed to the reject-function.

In ABAP we use a similar way to pass callbacks to asynchronous RFCs. We pass the addition PERFORMING subroutine ON END OF TASK or the addition CALLING method ON END OF TASK to the asynchronous RFC.
The following listing would be the ABAP equivalent to the fulFilledPromise in the example above.


FUNCTION 'ZASYNC_TASK'
* EXPORTING
*   VALUE(RETURN) TYPE BAPIRET2.
  
  WAIT UP TO 1 SECONDS.
  return = VALUE #( message = 'task successful' type = 'S' ).

ENDFUNCTION.

FORM callback USING task TYPE clike.
  DATA result TYPE bapiret2.

  RECEIVE RESULTS FROM FUNCTION 'ZASYNC_TASK'
    IMPORTING return = result.
  MESSAGE result-message TYPE result-type.
ENDFORM.

CALL FUNCTION 'ZASYNC_TASK'
  STARTING NEW TASK 'task_1'
  PERFORMING callback ON END OF TASK.

In JavaScript a rejected promise can be captured with a separate callback. In ABAP we use just one callback for successful or unsuccessful executions. If the ABAP-function raises a classical exception, we can catch it in the RECEIVE-statement.
The following listing would be the ABAP equivalent to the rejectedPromise in the example above.


FUNCTION 'ZFAILING_TASK'.
* EXCEPTIONS
*   validation_failure

  WAIT UP TO 2 SECONDS.
  RAISE validation_failure.
ENDFUNCTION.

FORM callback USING task TYPE clike.
  DATA: error_message(100).
  
  RECEIVE RESULTS FROM FUNCTION 'ZFAILING_TASK'
    EXCEPTIONS
      validation_failure = 4
      system_failure = 5 MESSAGE error_message.
      communication_failure = 6 MESSAGE error_message.

  CASE sy-subrc.
    WHEN 4.
     WRITE: 'Application raises validation_failure'. NEW-LINE.
    WHEN 5.
     WRITE: 'System failure: Check transaction ST22', error_message. NEW-LINE.
    WHEN 6.
     WRITE: 'Communication failure: Maybe they aren't enough free work-processes on your machine', error_message. NEW-LINE.
  ENDCASE.
ENDFORM.

CALL FUNCTION 'ZFAILING_TASK'
  STARTING NEW TASK 'task_1'
  PERFORMING callback ON END OF TASK.

Async functions

Async functions are another way to declare promises. From a technical point of view promises and async functions are identical.
Async functions are declared with the keyword async.


async function myFirstAsyncFunction(){
  await fulFilledPromise;
}

With the await statement, async functions can be used in a synchronous matter. We can wait for async functions as well as for promises. The await statement in the following listing causes the main task to wait until the timeout in the fulFilledPromise is reached.


(async () => {
  await myFirstAsyncFunction();
  console.log('Program end')
)();

When you execute this listing, first ‘{message: ‘task successful’, type: ‘S’}’ is printed out, afterwards ‘Program end’ is printed.

Rejected promises can be awaited, too.


async function wrapRejection(){
  await rejectedPromise;
}
(async () => {
  try{
    await wrapRejection();
  }catch(error){
    console.log(error);
  }
  console.log('Program end');
});

The exception passed to the reject-function is catched like an error thrown in a synchronous function.

Conclusion

In this lesson you learned the basics of concurrency. Promises and async functions are widely used in modern JavaScript libraries. So it’s important to understand them.

1 Comment
You must be Logged on to comment or reply to a post.
  • Hi Johannes,

    Great series of blogs.Liked the way you drew parallels between promises and RFCs in this blog. Makes it easy for ABAP developers to understand these concepts in JS.

    Thanks,

    Chetan