3

I've been having some issues with the inconsistencies between the JIT and AoT compilers. The most recent error that has stumped me was Error: Can't resolve all parameters for IndexedDBCache. IndexedDBCache is a service that depends on a string parameter:

Please note this issue also arises when I remove the 'protected' property!

// indexeddb-cache.ts
import { Injectable } from '@angular/core';

@Injectable()
export class IndexedDBCache {
  constructor(protected databaseName : string) {}
}

I'm using a factory to provide versions of the service:

// test-api.cache.factory.ts
import { IndexedDBCache } from '../indexeddb-cache/indexeddb-cache';

export function testIndexedDBCacheFactory() { return new IndexedDBCache('test'); }

// test-api.cache.ts
import { InjectionToken, Provider } from '@angular/core';
import { IndexedDBCache } from '../indexeddb-cache/indexeddb-cache';
import { testIndexedDBCacheFactory } from './test-api.cache.factory';

export const testIndexedDBCache = new InjectionToken<IndexedDBCache>('testIndexedDBCache');

export let testIndexedDBCacheProvider : Provider = {
  provide: testIndexedDBCache,
  useFactory: testIndexedDBCacheFactory
};

Note : These files have to be split according to func-in-providers-useFactory and arrow-function-exports - don't ask me why =/

Now the AoT compiler doesn't like this string paramter at all. I've looked into the issue but could only find reference to OpaqueToken (now depricated and replaced by InjectionToken<string>). My code would now read:

// test-api.cache.factory.ts
import { InjectionToken } from '@angular/core';
import { IndexedDBCache } from '../indexeddb-cache/indexeddb-cache';

const testIndexedDBCacheFactoryToken = new InjectionToken<string>('test');
export function testIndexedDBCacheFactory() { return new IndexedDBCache(testIndexedDBCacheFactoryToken); }

Obviously this is not compiling as the constructor would only allow for a string parameter. I don't have enough knowledge about InjectionTokens or the AoT issue at hand to solve this - anyone have a suggestion for a construct that would work?

More context on my code and issue to be found at angular/angular#17295.


Things I've tried:

  1. Removing the protected access modifier > Exact same error persists
  2. Removing the string parameter > Not an option - it defines the service
  3. Replacing the string parameter in the factory with an InjectionToken<string> > An InjectionToken is not a suitable parameter
Raven
  • 1,453
  • 3
  • 18
  • 29
  • `constructor(protected databaseName : string) {}` You cant do this, since this class is marked as @Injectable Angular will try inject that string in which it cannot do – Toxicable Jun 09 '17 at 11:45
  • @Toxicable It works fine when using JIT though. Is there an alternative way of setting up service factories based on a string? – Raven Jun 09 '17 at 11:48
  • if the class does not have `@Injectable()` Angular will not try inject it, this is the only way you can use the constructor – Toxicable Jun 09 '17 at 11:59
  • It does have `@Injectable()` and it works.. I have it running in JIT and in karma. – Raven Jun 09 '17 at 12:01
  • Running in JIT is not the same as running in AOT, so saying it works in one does not imply that it should work in the other – Toxicable Jun 09 '17 at 12:04
  • @Toxicable Still.. even if it doesn't work is there an alternative that does work? – Raven Jun 09 '17 at 12:17
  • Reworked my question and examples here: https://stackoverflow.com/questions/44461657/creating-aot-compatible-service-factories – Raven Jun 09 '17 at 15:34

1 Answers1

2

There was a misunderstanding of the issue at hand. The classes to be factoried are not services themselves and as such do not need the @Injectable property. More detail to be found at Creating AoT compatible Service Factories

Raven
  • 1,453
  • 3
  • 18
  • 29