2

I am using JavaScript, and I have an event hook for drag & drop. If I return false, the drop action will be aborted. Within that event hook I need to call an ASYNC function (to lookup an entity) as part of my decision making.

Hooks.on("dragdrop", (context, data) => {
   const pack = context.pack.get(data.packId); //ok, this is synchronous
   const item = pack.getEntity(data.id);  // BAD: async returns promise, not item
   if (item.type === "blah") {            // this fails, since I got a promise
      return false;   // rejects dragdrop action
   }
   return true;
});

I must have this hook (callback) return an appropriate value (true/false), but if I use a the ASYNC function getEntity() I won't get a value back, just a promise that will eventually return the item. How do I solve this problem?

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
toasty
  • 21
  • 2

2 Answers2

0

In general there are two main ways to wait for promises. The first approach is to do it asynchronously, using .then() and the like. This is a very good approach and in most cases should be used. However, in your specific example you intend to reject drag & drop if something returns false, so your current approach expects synchronous behaviour, but that's blocking Javascript's main thread. If that answer is slow or never arrives, then your users will be stuck on the page, not being able to perform any actions that would trigger Javascript functionalities. If you like this approach for the time being, then you can use await. But in order to await, you need to be inside an async function.

So, as you have probably guessed, you will need to separate your logic from UI event handling. Let the drag & drop perform normally and if the answer is false, then undo the event. Or, perform the drag & drop event, but put the given element into a temporary state while you wait for an answer and when the answer arrives (or it times out), then finalize the effects of the drop or undo it. So you will need to handle the UI event which would trigger some logical processing (preferably executed by web workers if it's processor-intensive) and once that's completed, the UI needs to handle the results.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

No, you can't do that using this hook API. That is a fully synchronous API, so it can't resolve async listeners/hooks.

You can use a custom EventEmitter with async listeners support to make your hook API asynchronous. Use EventEmitter2, which provides emitAsync method

Dmitriy Mozgovoy
  • 1,419
  • 2
  • 8
  • 7