Skip to content

Iterate over Promises #288

@Joxeur

Description

@Joxeur

I'm submitting a feature request

  • Library Version:
    1.4.0

Current behavior:

Currently one can't really easily iterate over the result of a Promise.

I am in a situation where I an array of Files and I need to extract their dimensions to be able to use http://photoswipe.com. Extracting those information is however an asynchronous task as one need to have the image loaded to get its dimension.

I wrote a ValueConverter that takes an array of Files and return a Promise containing the same list of Files with metadata. But I then needed to iterate over this Promise. It took me some time before I figured out what was the best way to do so.

I first tried with an asynchronous BindingBehavior. It worked when I was assigning a new array, but not when I was removing an item from the array. I could then get it to work by removing the item from a clone of my array and reassigning it to the original, but I didn't find it very elegant.

I then read about these RepeatStrategies and thought it would be a nice way to solve my problem. I then wrote a strategy for Promises that is just a wrapper to other already existing strategies:

import { Repeat, RepeatStrategyLocator } from 'aurelia-templating-resources';

export class PromiseRepeatStrategy {

  constructor(private repeatStrategyLocator: RepeatStrategyLocator){}

  instanceChanged(repeat: Repeat, promise: any): void {
    promise.then((items) => {
      const strategy = this.repeatStrategyLocator.getStrategy(items);
      if(!strategy){
        throw new Error('Value for \'' + items + '\' is non-repeatable');
      }
      strategy.instanceChanged(repeat, items);
    });
  }
  instanceMutated(repeat: Repeat, promise: any, changes: any): void {
    promise.then((items) => {
      const strategy = this.repeatStrategyLocator.getStrategy(items);
      if(!strategy){
        throw new Error('Value for \'' + items + '\' is non-repeatable');
      }
      strategy.instanceMutated(repeat, items, changes);
    });
  }
  getCollectionObserver(observerLocator: any, items: any): any {}
}

Then its registration

repeatStrategyLocator.addStrategy(items => items && typeof items.then === 'function', new PromiseRepeatStrategy(repeatStrategyLocator));

I thought it could help one facing the same problem and would be nice to have it directly native in the library.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions