Wait for a function's result


#1

Hey guys!

How can I display in a template some data that takes a while to be processed?
I’m uploading an image to S3, and as soon as it’s uploaded I’m using the url to get a list of colors in that image, using Imgix. I’m trying to display the list somewhere next to the image, but the problem is that it takes a while for imgix to generate and return the color list, so my helper is always returning ‘undefined’ (naturally).
What can I do to avoid this?

This is what I’m doing at the moment.

Template.sandbox_item.helpers({
palette: function (image) {
var finalColors = [];
if (image.percent_uploaded == 100) {
    var url  = new imgix.URL(...);
    url.getColors(6, function(colors) {
        colors.forEach(function (color) {
            var hex = colorToHex(color);
            finalColors.push(hex);
        });
    });
return finalColors;}
}

#2

if you’re using ES6, promisify it, show a loading screen, then do a .then() when it’s done.

var getColors = function (url) {
  return new Promise(function (resolve, reject) {
    let finalColors = [];
    url.getColors(6, function (colors) {
      colors.forEach(function (color) {
        var hex = colorToHex(color);
        finalColors.push(hex);
      });
      resolve(finalColors);
    });
  });
}

Then you can use the promise like this.

Loading.show({ message: 'Initializing colors...' });
let imgix = new imgix.URL();
getColors(imgix)
  .then(function (colors) {
    // you can use the colors now
    Loading.hide();
  });

#3

I’m probably doing something wrong because the helper still returns nothing. Basically what I did was to take the code from your second bit and put it inside my helper, like this:

Template.sandbox_item.helpers({
palette: function (image) {
    if (image.percent_uploaded == 100) {
        var url = new imgix.URL(...);
        getColors(url).then(function (colors) {
            console.log(colors);
            return colors;
        });
        console.log('test');
    }
}
});

Console output:

[Log] test
[Log] ["#453b49", "#566263", "#971e01", "#da46d", "#6dcba6", "#ffd807"] (6)

#4

yeah, it’s asynchronous, it doesn’t return. Do the operation in the callback, eg:

Loading.show();
getColors(url)
  .then((colors) => {
    let palette = $(this.find('#color-palette'));
    colors.forEach(function (color) {
      palette.append('<div style="background-color: ' + color.hex + ';">' + color.name +'</div>');
    });
  });