0

I need to interlace promises in my app:

  protected scroll<T>(path: string, pageSize: number, filter: string, data: T[]): Promise<T[]> {    
            let promise = new Promise<T[]>(function(resolve, reject) {
                this.httpClient
                    .get<T[]>(this.appConfigService.buildApiUrl(path), { params })
                    .toPromise<T[]>()
                    .then(result => {
                        if (result) {
                            resolve(data.concat(result));
                        }
                    })
                    .catch(function(e) {
                        reject(e);
                    });
            });

            return promise;
        }

My problem is that I receive following message: 'Untyped function calls may not accept type arguments'

How would I solve this?

UPDATE:

I should not have removed the if condition from the example:

  if (!filter) {
            const params = new HttpParams()
                .set('searchText', '')
                .set('skip', data.length.toString())
                .set('take', pageSize.toString());

            const promise = new Promise<T[]>((resolve, reject) => {
                this.httpClient
                    .get<T>(this.appConfigService.buildApiUrl(path), { params })
                    .toPromise<any>()
                    .then(result => {
                        if (result) {
                            resolve(data.concat(result));
                        }
                        resolve(data);
                    })
                    .catch(e => reject(e));
            });

            return promise;
        }
        // also returning a promise
        return this.filter<T>(data, pageSize, filter, path);
4
  • is it the toPromise() call that is causing it? Commented Oct 25, 2019 at 8:03
  • What line/statement is the error pointing to? Commented Oct 25, 2019 at 8:05
  • 1
    You use function(resolve, reject) {...} while addressing this.httpClient, but I don't see a bind(). I suggest you use arrow syntax: new Promise<T[]>((resolve, reject) => {...}). Commented Oct 25, 2019 at 8:08
  • The update doesn't fundamentally change anything. Commented Oct 25, 2019 at 9:05

1 Answer 1

1

There are a couple of problems there.

  1. The error message is because you're using <T[]> on get and toPromise, which aren't generic functions. Just apply the type T to result in the then handler.

  2. You're falling into the promise creation antipattern. You already have a promise (from this.httpClient), so you don't need new Promise.

  3. You're using a traditional function for your new Promise callback, but then using this within it as though it were still referring to your class instance. If you were going to keep the new Promise, you'd want an arrow function instead, so it closes over this.

Instead (see *** comments):

protected scroll<T>(path: string, pageSize: number, filter: string, data: T[]): Promise<T[]> {    
    // *** Return the result of calling `then` on the promise from `toPromise`
    return this.httpClient
        // *** Don't use <T[]> on `get` and `toPromise`
        .get(this.appConfigService.buildApiUrl(path), { params })
        .toPromise()
        .then((result: T) => { // *** <== Note the `T`
            // *** If it's really possible that `result` will be falsy and you don't want that
            // to be valid, you can do this:
            if (!result) {
                throw new Error("appropriate error here");
            }
            return data.concat(result);
        });
}

On the playground


UPDATE:

I should not have removed the if condition from the example:

It doesn't matter, just put the body of the above into the if block:

protected scroll<T>(path: string, pageSize: number, filter: string, data: T[]): Promise<T[]> {    
    if (!filter) {
        const params = new HttpParams()
           .set('searchText', '')
           .set('skip', data.length.toString())
           .set('take', pageSize.toString());

        return this.httpClient
            // *** Don't use <T[]> on `get` and `toPromise`
            .get(this.appConfigService.buildApiUrl(path), { params })
            .toPromise()
            .then((result: T) => { // *** <== Note the `T`
                // *** If it's really possible that `result` will be falsy and you don't want that
                // to be valid, you can do this:
                if (!result) {
                    throw new Error("appropriate error here");
                }
                return data.concat(result);
            });
    }
    return this.filter<T>(data, pageSize, filter, path);
}
Sign up to request clarification or add additional context in comments.

2 Comments

1 -> I need to specify T[] in order to apply concat on the result. 2. -> I don't see how you want to be able to fetch the result and apply concatting without using a .then() block.
@yBother - 1. No, you don't, see the type I applied to result (I should have called that out). 2. Oops, missed the concat, fixed. BTW, your update to the question doesn't fundamentally change anything.

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.