-1

So I have the following code [that came from one of the examples on Font Face Observer Github]

var fontA = new FontFaceObserver('Family A');
var fontB = new FontFaceObserver('Family B');

Promise.all([fontA.load(), fontB.load()]).then(function () {
  console.log('Family A & B have loaded');
});

I'm trying to rewrite this in such a way that I can compose the array that contains [and executes] the functions i.e. [fontA.load(), fontB.load()] in a dynamic manner using push.

Here's what I have so far.

var font_arr = ['Family A', 'Family B'];
var font_item_obj;
var font_load_item_res;
var font_load_arr = [];
for(var i = 0; i < font_arr.length; i++)
{
   font_item_obj = new FontFaceObserver(font_arr[i]);
   font_load_item_res = function(){
      font_item_obj.load();
   };
   font_load_arr.push(font_load_item_res);
}

Promise.all(font_load_arr).then(function () {
    console.log('Family A & B have loaded');
});

The console message is displayed as expected, but I can't help feeling that there's a better way to write this. Also, I get a warning in WebStorm saying Mutable variable is available from closure where you have this code: font_item_obj.load();

EDIT

The code needs to work on IE8 so Array's map method may not be viable.

UPDATE

I was able to find the answer using guidance from @SkinnyJ and @MinusFour; using the map function appears to work best. Here's the updated code:

var font_arr = [{'font-family': 'Family A', 'font-options': {}}, {'font-family': 'Family B', 'font-options': {}}];

function loadFont(font_obj)
{
    var font_obj_family_str = font_obj['font-family'];
    var font_obj_options_obj = font_obj['font-options'];

    var font_load_obj = new FontFaceObserver(font_obj_family_str, font_obj_options_obj);
    return font_load_obj.load();
}

Promise.all(font_arr.map(loadFont)).then(function () {
    console.log('Family A & B have loaded');
});

It's quite easy to create an iterable object (in this case font_arr) using a for loop. Also, I found a shim for map on IE8 here so that should solve the browser requirement.

Community
  • 1
  • 1
ObiHill
  • 11,448
  • 20
  • 86
  • 135
  • What exactly is wrong with your second implementation? – jfriend00 Apr 25 '16 at 18:52
  • As mentioned in the question there is a validation warning – ObiHill Apr 25 '16 at 20:47
  • So, is your entire question about the validation warning? If so, please change the title to reflect that and make sure that is explicitly stated in the question. Right now, we can't really tell what you're asking. – jfriend00 Apr 25 '16 at 21:18
  • No, you can't tell what I'm asking. The answers below have pointed me in the right direction. I'll look into the title. – ObiHill Apr 25 '16 at 21:35

2 Answers2

2

Can you just use Array.prototype.map on an array that you dynamically create?

var fonts = [];
fonts.push('Family A');
fonts.push('Family B');

Promise.all(fonts.map(font => new FontFaceObserver(font).load()))
  .then(() => console.log('Family A & B have loaded'));
Yosef Weiner
  • 5,432
  • 1
  • 24
  • 37
  • `Promise.all()` expects an actual array of promises as its argument, so you don't want the `.apply()` here. I thought your answer was good, you just need to use `Promise.all()` instead of `Promise.all.apply()`. – jfriend00 Apr 25 '16 at 18:53
  • @jfriend00 Thanks, but now I really don't understand the question. I've modified the answer but somehow I don't think this is what the OP is asking. – Yosef Weiner Apr 25 '16 at 18:57
  • Yeah, that's why I asked to OP to clarify what is wrong with their second code block. I'm not sure either. – jfriend00 Apr 25 '16 at 18:58
  • @SkinnyJ Thanks. This would have worked, but I forgot to mention that it needs to work with IE8. As far as I know Array's map is not supported. – ObiHill Apr 25 '16 at 20:45
  • @SkinnyJ Found my answer using the map function. I'll use a shim to take care of Array.map on IE8 – ObiHill Apr 25 '16 at 21:37
2

It's just easier to do with map:

var font_arr = ['Family A', 'Family B'],
    font_objs = font_arr.map(fm => new FontFaceObserver(fm));

Promise.all(font_objs.map(obj => obj.load())).then(function(){
    //all loaded
});
MinusFour
  • 13,913
  • 3
  • 30
  • 39