0

I try to build a keyword list from all existing keywords. I manage to retrieve them all and output them in the debug console.

I am confused about how and when to call resolve(taxonomyKeywords). I like to call it when all loops and their inner loops are finished. I tried using foreach, yet run in the same issue. Is my approach way off and there's a much easier way?

private searchKeyword(searchTerm: string, results: ITag[]) : ITag[] | Promise<ITag[]>
{
  return new Promise<IPersonaProps[]>( (resolve, reject) => {
    let taxonomyKeywords : ITag[] = [];

    this.props.taxonomyProvider.getTermStores().then( (stores: ITermStore[]) => {
      for(var store of stores )
      {
        this.props.taxonomyProvider.getTermGroups( store.id ).then( (groups: ITermGroup[]) => {

          for(var group of groups)
          {
            this.props.taxonomyProvider.getTermSets(group).then( (sets: ITermSet[]) => {
              for(var termSet of sets)
              {
                this.props.taxonomyProvider.getTerms(termSet).then( (terms: ITerm[]) => {
                  for(var term of terms)
                  {
                    if( term.name.indexOf(searchTerm) >= 0 )
                    {
                      taxonomyKeywords.push( { key: term.name, name: term.name} );
}}});}});}});}});});}
2
  • 1
    You never should call resolve, as you should avoid the Promise constructor antipattern! Commented Jul 11, 2017 at 6:02
  • 1
    You should be using map and Promise.all, not forEach Commented Jul 11, 2017 at 6:02

1 Answer 1

1

I think below pattern shall be better:

private function searchKeyword(searchTerm: string, results: ITag[]): ITag[] | Promise<ITag[]> {

    return this.props.taxonomyProvider
        .getTermStores()
        .then((stores: ITermStore[]) => {
            return Promise.all(stores.map(s => this.props.taxonomyProvider.getTermGroups(s.id)));
        })
        .then((groups: Array<ITermGroup[]>) => {

            const flattenGroups: ITermGroup[] = groups.reduce((p, c) => p.concat(c), []);

            return Promise.all(flattenGroups.map(g => this.props.taxonomyProvider.getTermSets(g)));
        })
        .then((sets: Array<ITermSet[]>) => {
            const flattenSets: ITermSet[] = sets.reduce((p, c) => p.concat(c), []);

            return Promise.all(flattenSets.map(s => this.props.taxonomyProvider.getTerms(s)));
        })
        .then((terms: Array<ITerm[]) => {
            const flattenTerms: ITerm[] = terms.reduce((p, c) => p.concat(c), []);
            return flattenTerms
                .filter(t => t.name.indexOf(searchTerm) >= 0)
                .map(t => ({ key: t.name, name: t.name }));
        });
}

You should learn how promise work

Sign up to request clarification or add additional context in comments.

4 Comments

Re: "learn how promise work" - I am trying to :-) It's more the mapping thing. I give your pattern a go ... Thanks a lot already :-)
This doesn't work. Those taxonomyProvider.getXY methods all return promises, and you cannot just return an array of promises from then
I think that is the error I am getting now: Error - typescript - : error TS2345: Argument of type '(groups: ITermGroup[][]) => Promise<ITermSet[]>[]' is not assignable to parameter of type '(value: Promise<ITermGroup[]>[]) => Promise<ITermSet[]>[] | PromiseLike<Promise<ITermSet[]>[]>'.
Awesome thanks a lot that worked like a charm and I am learning :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.