0

I'm trying to understand contexts in Loopback 4.

One thing which doesn't make sense to me is how Loopback could tell what the context should be if there were ever two asynchronous queries running in parallel.

As in:

const ctx;

for (let i = 0; i < 10; i++) {
  ctx.set("i", i);
  endpointCall();
}

async function endpointCall() {
  return new Promise((resolve) => {
    setTimeout(
      () => { resolve `The context variable i equals ${ctx.get(i)}`,
      Math.random() * 500,
    )

  });
}

Obviously the above would not work. In fact, no way that I can imagine it would Loopback be able to tell what the context is two or more endpoints were being waited on at the same time.

So does loopback 4.0 run queries in parallel ever?


Aware: JS is single threaded, but the engines which run JS typically are not. For instance, the engine can multi-thread reading multiple fetches at the same time. It will still only serve the data to the JS environment synchronously.


Clarity: Which of the following is more like loopback

Does loopback wait for the last api call to finish before starting the next, or does it ever run them in an async-parallel fashion?

Seph Reed
  • 8,797
  • 11
  • 60
  • 125

1 Answers1

0

No, it does not. But that's a characteristic of JavaScript.


The code snippet seems to be incomplete. Hence, for the clarity, let's assume the following code is used:

const Context = require('@loopback/context').Context;

const ctx = new Context();

async function main() {
  for (let i = 0; i < 10; i++) {
    ctx.bind('i').to(i);

    new Promise(() => {
      setTimeout(
        async () => {
          console.log(`The context variable i equals ${await ctx.get('i')}`);
        },
        Math.random() * 500,
      )
    });
  }
}

main()

It achieves the same goals as the original code snippet:

  • Loop 10 times
  • Rebind value of 'i' by an increment of 1
  • Call ctx.get() after a "random" duration
  • Puts setTimeout in its own Promise

We're using @loopback/context directly as the @loopback/rest wrapper functions calls them internally.

We're also not resolve-ing as there's no practical difference in this example (We're not await-ing nor using the response).


how Loopback could tell what the context should be if there were ever two asynchronous queries running in parallel

While ctx.get() and ctx.bind() are asynchronous functions, JavaScript is still single-threaded. This means that these functions will be queued into the event loop and will therefore write or read the state on a first-come-first-serve basis.

However, a for-loop will block the event loop. This means that spinning up another Promise without await-ing for it to resolve will result in that Promise being hogged back by the for-loop.

Asynchronicity is not the same as multi-threaded. This means there will always be a queue and there isn't the same "race condition" as multi-threaded programming languages.

The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9
The context variable i equals 9

The results are the same with ctx.getSync().


Therefore, LoopBack Context does not process queries in parallel as JavaScript is single-threaded.

Further reading:

Rifa Achrinza
  • 1,555
  • 9
  • 19
  • There seems to be a misunderstanding here about what I'm asking. I've edited the question. From your answer, it appears that Loopback does in fact run multiple async api calls during the same time span (though obviously single threaded). Either that or there would be an `await endpointCall()` in the example. – Seph Reed Apr 21 '20 at 16:55