1

I want to create a function that enqueues callback functions, but doesn't return until that callback has been dequeued and executed.

function executeCallback(callback) {
    if( shouldEnqueue ) {
      enqueue(callback);
      // awaits execution of callback
      // return executed callback's return value
    } else {
      return callback()
    }
}

The actual function works as follows. When an orderbook is needed, we will check to see if we have a recent one cached. If we don't have a recent one, we will queue the request for a fresh orderbook. We will then return the orderbook once it has been requested. The actual code will look something like this:

const axios = require("axios");
const moment = require("moment");
const { promisify } = require("util");

const orderbookQueue = [];
const orderbookUpdateTime = {};

async function requestOrderbook(pair) {
  const response = await axios.post("https://api.kraken.com/0/public/Depth", {
    pair
  });
  orderbookUpdateTime[pair] = +moment();
  return response.data.result[pair];
}

async function getOrderbook(pair, currentTime) {
  if (
    orderbookUpdateTime[pair] &&
    currentTime - orderbookUpdateTime[pair] > 60000
  ) {
    const requestOrderbookAsync = promisify(requestOrderbook);
    orderbookQueue.push(() => requestOrderbookAsync(pair));
    // how to I return the result of requestOrderbookAsync when it has been called ?
  }
  return requestOrderbook(pair);
}

const queueExecutor = function queueExecutor() {
  while (orderbookQueue.length) {
    orderbookQueue[0]();
    orderbookQueue.shift();
  }
};
icey-t
  • 283
  • 3
  • 11

2 Answers2

0

1. Convert you callbacks to promise

E.g, convert

function mutilpy(a, b, callback) {
    let result = a*b;
    return callback(result);
}

to

function multiply(a, b) {
    return new Promise(function(resolve, reject) {
        let result = a*b;
        resolve(result);
    })
}

2. (Sort of) Enqueue your callbacks for completion

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = multiply(10,3);

Promise.all([promise1, promise2, promise3]).then(function(values) {
    // YOU GET HERE WHEN ALL PROMISES ARE RESOLVED
    console.log(values);
});
// expected output: Array [3, 42, 30]
eMad
  • 998
  • 3
  • 13
  • 31
  • 1
    I need to return the resolved promise to each user, in order, when they request the data. So new requests will be enqueued at random times. The resolved promises need to be returned as soon as they are resolved. – icey-t May 24 '18 at 21:44
0

I found a solution that works for me. One can extract the resolve function from a new Promise, enqueue the resolve function in a different scope, then dequeue and execute the resolve function whenever the time comes, in any scope.

Resolve Javascript Promise outside function scope

icey-t
  • 283
  • 3
  • 11