-3

My program downloads a large amount of data, processes it, and makes it available through a returned function. The program gets ahread of the download, so I am adding promises to make it wait for the data to arrive.

function dataSource(...) {

  var _data = null;

  // download: a promise that returns data for the _data object.
  let download = function() { ... }

  return function(...) {

    if (!_data) {
      download(...).then(data => _data = data).done();
    }

    var datum = _data[key];
    var outbound = doSomethingWithData(datum);
    return outbound;
  }

}

My code is structured like this because the function that Engine returns makes my code very neat.

var generate = dataSource(param1,param2);
var fullName = generate("malename")+" "+generate("malename")+" "+generate("surname");

The specific requirements are:

  1. Download the data only once.
  2. Query the data by key any number of times without downloading the data again.
  3. Do not change the existing interface.

I could have dataSource return a promise rather than a function. I know what the pattern for using promises looks like. But that will force me to rewrite the code that consumes this function. This pattern is used extensively throughout the code, and changing it isn't an acceptable solution.

How can I structure this to ensure that my function doesn't return until it has the data, without returning the promise?

Jay Bienvenu
  • 3,069
  • 5
  • 33
  • 44
  • 1
    Possible duplicate of [How to return value from an asynchronous callback function?](http://stackoverflow.com/questions/6847697/how-to-return-value-from-an-asynchronous-callback-function) – Hacketo Mar 03 '16 at 13:58
  • Not a duplicate of that question at all. Different requirements. – Jay Bienvenu Mar 03 '16 at 14:32

2 Answers2

0

This should fix it

function dataSource(){
    return function(){
        return download(...).then(data=>doSomethingWithData(data[key]));
    };
}
var generate = dataSource();
Promise
.all(["malename","malename","surname"].map((name)=>return generate(name)))
.spread((name1,name2,name3)=>{
    return [name1,name2,name2].join(" ");
});

the spread is not needed, but it helps for illustration purposes

aclave1
  • 1,680
  • 18
  • 29
-2

Have dataSource return a promise rather than the data function. The revised dataSource looks like this:

function dataSource(...) {

  var _data = null;

  // download: a promise that returns data for the _data object.
  let download = function() { ... }

  function _generate(...) {...}

  return download(group,subgroup,options).then(data => _data = data).then(() => _generate);
}

Then, where the code is consumed, get the generate function from the returned promise:

let generate = function() {};
dataSource.then(fn => generate = fn).done();
Jay Bienvenu
  • 3,069
  • 5
  • 33
  • 44