Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null

I am trying to a sample observable working but I am getting this error.

EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null
browser_adapter.js:77EXCEPTION: Error: Uncaught (in promise): TypeError: Cannot read property 'query' of nullBrowserDomAdapter.logError @ browser_adapter.js:77BrowserDomAdapter.logGroup @ browser_adapter.js:87ExceptionHandler.call @ exception_handler.js:57(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
browser_adapter.js:77STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:59(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
browser_adapter.js:77Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null
    at resolvePromise (zone.js:538)
    at resolvePromise (zone.js:523)
    at zone.js:571
    at ZoneDelegate.invokeTask (zone.js:356)
    at Object.onInvokeTask (ng_zone_impl.js:36)
    at ZoneDelegate.invokeTask (zone.js:355)
    at Zone.runTask (zone.js:256)
    at drainMicroTaskQueue (zone.js:474)
    at XMLHttpRequest.ZoneTask.invoke (zone.js:426)BrowserDomAdapter.logError @ browser_adapter.js:77ExceptionHandler.call @ exception_handler.js:60(anonymous function) @ application_ref.js:265schedulerFn @ async.js:123SafeSubscriber.__tryOrUnsub @ Subscriber.js:225SafeSubscriber.next @ Subscriber.js:174Subscriber._next @ Subscriber.js:124Subscriber.next @ Subscriber.js:88Subject._finalNext @ Subject.js:128Subject._next @ Subject.js:120Subject.next @ Subject.js:77EventEmitter.emit @ async.js:112onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:66ZoneDelegate.handleError @ zone.js:327Zone.runGuarded @ zone.js:233_loop_1 @ zone.js:487drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
zone.js:461 Unhandled Promise rejection: Cannot read property 'query' of null ; Zone: angular ; Task: Promise.then ; Value: TypeError: Cannot read property 'query' of null(…)consoleError @ zone.js:461_loop_1 @ zone.js:490drainMicroTaskQueue @ zone.js:494ZoneTask.invoke @ zone.js:426
zone.js:463 Error: Uncaught (in promise): TypeError: Cannot read property 'query' of null(…)

Below is my code in app.js

import {Component, ViewChild} from '@angular/core';
import {App,ionicBootstrap, Platform, MenuController} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Page1} from './pages/page1/page1';
import {Page2} from './pages/page2/page2';
import {Page3} from './pages/page3/page3';
import {SampleService} from './services/sample-sevice';
@App({
 templateUrl: 'build/app.html',
 providers: [SampleService],
 queries: {
    nav: new ViewChild('content')
  }
})

export class MyApp {
  static get parameters() {
   return [[Platform], [MenuController]];
  }

  constructor(platform, menu) {
    this.platform = platform;
    this.menu = menu;
    
    // set our app's pages
    this.pages = [
      { title: 'Home', component: TabsPage },
      { title: 'Events', component: Page1 },
      { title: 'News & Articles', component: Page2 },
      { title: 'Library', component: Page3 },
      { title: 'My Account', component: Page3 },
    ];

    // make HelloIonicPage the root (or first) page
    this.rootPage = TabsPage;
 }
 
initializeApp(){
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }
    
      openPage(page) {
    // close the menu when clicking a link from the menu
    this.menu.close();
    // navigate to the new page if it is not the current page
    this.nav.setRoot(page.component);
  }
}

code in service:

import {Injectable} from '@angular/core';
import {Http, Headers, RequestOptions} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
@Injectable()
export class SampleService {

    static get parameters() {
        return [[Http]];
    }

    constructor (http) {
        this.http = http;
    }

    findAll() {
        console.log("service called");
        return this.http.get('http://jsonplaceholder.typicode.com/posts')
            .map(res => res.json())
            .catch(this.handleError);
    }

    handleError(error) {
        console.error("server" + error);
        return Observable.throw(error.json().error || 'Server error');
    }

}

If the error message says it can’t read the property ‘query’ of something, the place to look would be where you are referencing a ‘query’ property of something. I don’t see it in what you’ve posted.

In your service, I don’t know what you are trying to return. If you just want an observable, you can just do:

return this.http.get('http://jsonplaceholder.typicode.com/posts').

Next in your controller, you can do this:

sampleService.findAll()
.map(res => res.json())
.catch(this.handleError)
.subscribe((data) => {
  //your code goes here
});

Or if you want to resolve the data and return a promise then do this:

return new Promise((resolve, reject) => {
           this.http.get('http://jsonplaceholder.typicode.com/posts')
            .map(res => res.json())
            .catch(this.handleError)
            .subscribe(function (data) {
                resolve(data.data);
            });
});

Then in your controller you can do this:

sampleService.findAll()  
.then((data) => {
  //your code goes here
});
2 Likes

I find Observable.toPromise() much more readable than explicitly instantiating the Promise yourself, but I think we agree that there isn’t really any good reason not to just return the Observable and forget all about promises in this situation.

1 Like

Good point @rapropos. If you just want to convert the Observable to a promise, toPromise() is the way to go.

However, I assumed that the OP had wanted to manipulate the data before returning it, which is why I provided the example of creating a new promise.

Can’t you do any manipulation desired either via Rx operators like map before calling toPromise or in a then chain afterwards?

1 Like

this is my code which subscribes to the observable from the service. @rapropos

I adopted the pattern which @beetz12 posted above.

page1.js

import {Page} from 'ionic-angular';
import {OnInit} from '@angular/core';
import {SampleService} from '../../services/sample-sevice';

@Page({
  templateUrl: 'build/pages/page1/page1.html',
  providers: [SampleService]
})
export class Page1 {

  static get parameters() {
   return [[SampleService]];
  }
  
  constructor(sampleService) {
    this.sampleService = sampleService;
  }
  
  ngOnInit() {
   this.sampleService.findAll()
      .map(res => res.json())
      .catch(this.handleError)
        .subscribe((data) => {
   console.log("data here ", data);
});
    }
}

Now I am able to get the data, but I read that Service should be singleton and should not be injected in each controller you need. So initially I din’t define the provider at class level, but it was giving “sampleService” not defined error so I ended up defining them in each class. Not sure why this happens though, since I have it injected at app level.

this is my folder structure
image

Sorry, I can’t help any further because I hate JavaScript. Hope you get it working.

2 Likes

Great work, you are almost there.

To make your service singleton, you just need to bootstrap it in app.js (if you are using ionic2 beta 8 or later):

ionicBootstrap(yourApp, [SampleService], {});

Then all you need to do is just inject the service into your controller. Because you bootstrapped the service in app.js, it will automatically create a singleton instance.

Hope this helps.

1 Like

I get this error if I add it to my app.js

app.js:63Uncaught TypeError: (0 , _ionicAngular.ionicBootstrap) is not a function

wondering if its because of javascript. I could find the syntax only for typescipt in ionic api docs.

import {Component, ViewChild} from '@angular/core';
import {App,ionicBootstrap, Platform, MenuController} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Page1} from './pages/page1/page1';
import {Page2} from './pages/page2/page2';
import {Page3} from './pages/page3/page3';
import {SampleService} from './services/sample-sevice';

@App({
 templateUrl: 'build/app.html',
 providers: [SampleService],
 queries: {
    nav: new ViewChild('content')
  }
})

export class MyApp {
  static get parameters() {
   return [[Platform], [MenuController]];
  }

  constructor(platform, menu) {
    this.platform = platform;
    this.menu = menu;
    
    // set our app's pages
    this.pages = [
      { title: 'Home', component: TabsPage },
      { title: 'Events', component: Page1 },
      { title: 'News & Articles', component: Page2 },
      { title: 'Library', component: Page3 },
      { title: 'My Account', component: Page3 },
    ];

    // make HelloIonicPage the root (or first) page
    this.rootPage = TabsPage;
 }
 
initializeApp(){
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }
    
      openPage(page) {
    // close the menu when clicking a link from the menu
    this.menu.close();
    // navigate to the new page if it is not the current page
    this.nav.setRoot(page.component);
  }
    
 
}

ionicBootstrap(MyApp, [SampleService], {});

What version of ionic-angular are you running? You can check your package.json.

ionicBootstrap is only available in ionic-angular 2.0.0-beta.8 or later. You probably have an earlier version and in that case just remove the ionicBootstrap and keep providers: [SampleService].

Let me know if that works.

Yeh just noticed that mine is older. 2.0.0-beta.7

but yeh providers works :slight_smile: not sure why it was not working before

thanks a bunch… you guys are awesome :slight_smile: