6

I have a test data service written in Angular4. It currently looks like this:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

import 'rxjs/add/operator/map';

import 'rxjs/add/operator/toPromise'


@Injectable()
export class DataService {

  constructor(private http: Http) { }

fetchData(){
  return this.http.get('https://dinstruct-d4b62.firebaseio.com/.json').map(
    (res) => res.json()).toPromise();
}

}

With thanks to "The Net Ninja" for this code, as this section of the app is basically exactly the same as the tutorial code (I prefer to have something that should be a known working example for testing purposes when building new apps)...

The problem is that though there is definitely test data at https://dinstruct-d4b62.firebaseio.com/.json, which is not hidden or firewalled in any way as far as I can tell (directly accessible via browser), when the app enters the fetchData() function, it logs:

    ERROR Error: Uncaught (in promise): Error: Response with status: 404 Not Found for URL: https://dinstruct-d4b62.firebaseio.com/.json
Error: Response with status: 404 Not Found for URL: https://dinstruct-d4b62.firebaseio.com/.json

at the start of the stack trace. What could be going on here?

Update:

I also noticed that in the calling function:

ngOnInit(): void {
  this.customerService.getCustomers()
      .then(customers => this.customers = customers);
  this.dataService.fetchData().subscribe(
    (data) => console.log(data));
}

When I have this.dataService.fetchData().subscribe((data) => console.log(data)); in the code, clicking a link to the dashboard it momentarily shows localhost:3000/dashboard in the browser address bar but then immediate flicks back to showing the previous URL. However, when I remove this line, the app correctly shows localhost:3000/dashboard the whole time. I assume this is probably related to the console.logged 404 error.

Also perplexing is that when I check the network traffic, no 404 is shown.

Update:

When the observable is change to a promise I get this output in the console:

Response {_body: Object, status: 404, ok: false, statusText: "Not Found", headers: Headers…}
headers
:
Headers
ok
:
false
status
:
404
statusText
:
"Not Found"
type
:
null
url
:
"https://dinstruct-d4b62.firebaseio.com/.json"
_body
:
Object
error
:
"Collection 'undefined' not found"
__proto__
:
Object
constructor
:
function Object()
hasOwnProperty
:
function hasOwnProperty()
isPrototypeOf
:
function isPrototypeOf()
propertyIsEnumerable
:
function propertyIsEnumerable()
toLocaleString
:
function toLocaleString()
toString
:
function ()
valueOf
:
function valueOf()
__defineGetter__
:
function __defineGetter__()
__defineSetter__
:
function __defineSetter__()
__lookupGetter__
:
function __lookupGetter__()
__lookupSetter__
:
function __lookupSetter__()
get __proto__
:
function __proto__()
set __proto__
:
function __proto__()
__proto__
:
Body
constructor
:
function Response(responseOptions)
toString
:
function ()
__proto__
:
Object

There is still no 404 in the network traffic.

I have now updated the calling function to this:

ngOnInit(): void {
  this.customerService.getCustomers()
      .then(customers => this.customers = customers);
  this.dataService.fetchData().then((data) => {
       console.log(data);
  })
       .catch((error) => console.error(error));
}
  • missing model name? – MilkyWayJoe May 30 '17 at 20:04
  • Works fine for me when I tested, you have not used in memory web api before by any chance? – AT82 May 30 '17 at 20:12
  • I created a plunker with the URL, and it's returning data just fine. Check if you have all the modules imported correctly. http://plnkr.co/edit/MMly1tMo2ZOI2cIWqnit?p=preview – Nehal May 30 '17 at 20:17
  • there are no module errors; I guess there's something between the code and the exchange of data –  May 30 '17 at 21:03
  • am I allowed to say MitM? Though without full information transform visibility that's probably more a wild guess –  May 30 '17 at 21:04
  • @MilkyWayJoe what do you mean by missing model name? It's just getting json data from a server. –  May 30 '17 at 21:09
  • @JustInTimeBerlake I see you use `.map()`, have you imported Rxjs correctly? `import 'rxjs/add/operator/map';` – Simone Mazzoni May 31 '17 at 09:18
  • I added `import 'rxjs/add/operator/map';`. It's still doing the same thing. –  May 31 '17 at 13:01
  • @AJT_82 could the in memory web api be interfering with the accessing of the external data? I'll try removing it... –  Jun 01 '17 at 11:39
  • Yes, it absolutely does, that's why I asked. – AT82 Jun 01 '17 at 11:40
  • @AJT_82 sorry I overlooked your comment. Yes, removing this fixed the problem. Feel free to put in an answer. –  Jun 01 '17 at 11:42
  • 1
    No problem, glad we sorted it out though! Even if it took a while :) – AT82 Jun 01 '17 at 11:47

3 Answers3

10

The in-memory-web-api will interfere with your "outside" requests. You need to remove that from your NgModule, since otherwise Angular is always trying to look in in-memory-web-api for your requests, which obviously doesn't exist in that place. So removing the equivalent of

InMemoryWebApiModule.forRoot(InMemoryDataService)

from your ngModule and that should clear it out! :)

AT82
  • 71,416
  • 24
  • 140
  • 167
  • Now get `XMLHttpRequest cannot load https://console.firebase.google.com/project/dinstruct-d4b62/database/data/.json/NaN. Redirect from 'https://console.firebase.google.com/project/dinstruct-d4b62/database/data/.json/NaN' to 'https://accounts.google.com/ServiceLogin?passive=1209600&osid=1&continue=ht…onsole.firebase.google.com/project/dinstruct-d4b62/database/data/.json/NaN' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.` But a) that's not the 404 I asked about and b) I can fix that –  Jun 01 '17 at 11:48
  • 1
    That is a CORS issue, you need to enable cors on server side. I'm not really familiar with firebase, so I cannot really help you there with more details. Sometimes though this is just caused by browser (as well), so you could try and enable cors in your browser, here's extension for chrome: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi HOPEFULLY this would clear it out, but usually we aren't that lucky ;) – AT82 Jun 01 '17 at 11:52
  • `private headers = new Headers({'Content-Type': 'application/json', 'Access-Control-Allow-Origin': 'https://dinstruct-d4b62.firebaseio'});` Of course now it's returning an empty promise... the debugging goes on *deep in thought chin-scratchy emojii* –  Jun 01 '17 at 12:07
  • I can see that emoiji in my head :D I said you need to enable cors (set the headers server-side), not in Angular :) – AT82 Jun 01 '17 at 12:12
  • Yeah, I know, but for some reason enabling it in Angular actually did clear up the CORS error and I'm now receiving the JSON data (it's just being converted to an empty promise) so even if this technically shouldn't have fixed it, it worked, so I'm not gonna question it. –  Jun 01 '17 at 12:13
  • That is the strangest thing I heard, that enabling headers in front-side would work :D :D Oh well, I guess it was some kind of magic :D Hold on, I'll make a demo for you with your json. Do you want to use promises or observables for this. You seem to mix them with `map` and `toPromise()` – AT82 Jun 01 '17 at 12:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145633/discussion-between-just-in-time-berlake-and-ajt-82). –  Jun 01 '17 at 12:19
  • This: https://stackoverflow.com/questions/27145287/angularjs-http-get-returns-error-with-status-0 might be useful reading for people about the way Angular handles CORS. –  Jun 01 '17 at 12:39
0

Try importing import 'rxjs/add/operator/toPromise'; and add toPromise to the end of the http get in the the fetchData() function.

fetchData(){
    return this.http.get('https://dinstruct-d4b62.firebaseio.com/.json').map(
    (res) => res.json()).toPromise();
}

Your calling function should then look like this:

this.dataService.fetchData()
    .then((data) => {
        console.log(data);
    })
    .catch((error) => console.error(error)); 
JSONGagnon
  • 87
  • 2
  • 15
  • This solves the browser address glitch and another unrelated issue, but the original problem still remains. –  May 31 '17 at 14:05
  • I'm getting a 404 in the console still and still no 404 in the network traffic. –  May 31 '17 at 14:09
  • I just tried running the code I edited and I am receiving the data in the console. Could you please edit the question to show the edits you have made to your files. – JSONGagnon May 31 '17 at 14:18
  • Edits posted as currently appear in code. There has been no fix to the main app error as a result of making the suggested edits. –  May 31 '17 at 14:28
  • Both your previous version and the updates I made work for me. I am unsure what is causing this error since it is working perfectly for me and a few others. Have you tried recompiling the app? Or using another web browser? – JSONGagnon May 31 '17 at 14:35
  • I tried another web browser and I've tried recompiling. Nothing seems to work. –  May 31 '17 at 14:38
0

In AppModule.ts where you have imports[], you would have imported the HttpClientInMemoryWebApiModule like =>


HttpClientInMemoryWebApiModule
    .forRoot(
      InMemoryService, { dataEncapsulation: false }
    ), 

Now What is happening here is that your application is searching for the public API in the in-memory web API only to solve this just tell In memory module not to behave like that by setting the passing though unknown Url true like =>


HttpClientInMemoryWebApiModule
    .forRoot(
      InMemoryService, { dataEncapsulation: false, passThruUnknownUrl: true }
    )