0

What i'm trying to do is to save all the static of my website in a json file that i want to read in angular, i was thinking about two ways of do it:

  1. Call a json file directly from AngularJS
  2. Send the json file from node to AngularJS

I don't know how to do either of them, i've tried the second way like this(no luck):

Nodejs code:

app.get( '/content', function ( require, response ) {
    response.setHeader('Content-Type', 'application/json');
    response.json( readJSONFile( './client/content.json', function ( err, json ) {
            if ( err ) {
                throw err;
            }
            console.log( json );
        } )
    )
} );

function readJSONFile( filename, callback ) {
    require( "fs" ).readFile( filename, function ( err, data ) {
        if ( err ) {
            callback( err );
            return;
        }
        try {
            callback( null, JSON.parse( data ) );
        } catch ( exception ) {
            callback( exception );
        }
    } );
}

When i access to localhost:3000/content and i check the network on the browser the file is sent, but i can't see the data in the preview tab, not sure of what i'm doing wrong...

Also how could i make a service to get this data from the server in AngularJS?

Jonathan Solorzano
  • 6,812
  • 20
  • 70
  • 131

1 Answers1

1

So your question can be broken down into 2 (quite) separate questions. Let's go one by one:

1. How to serve a json file from a Node.js app

The reason your code didn't work was that you did it in a "wrong order". Your readJSONFile function is an asynchronous one, where the content of the json file is only available after a while, when the callback block of Node's readFile function is invoked. Here, you are trying to use the immediate return value of readJSONFile as a parameter to response.json, which means undefined. And that is why you couldn't see any data in the preview tab.

The solutions:

a. You can use readFileSync instead for simplicity:

app.get( '/content', function ( request, response ) {
    response.json( require('fs').readFileSync('./client/content.json', 'utf8') );
}

b. Or to live by Node.js' asynchrony signature (also a better practice), you could do something like this:

app.get( '/content', function ( request, response ) {
    readJSONFile( './client/content.json', function ( err, json ) {
        if ( err ) {
            throw err;
        }
        return response.json( json );
    } );
} );

I'd suggest you google readFile and readFileSync to have a more solid understanding on these native Node.js APIs. Either way, both approaches should give you some data in the console preview tab. Now what's left is for the next question:

2. How to make requests to an HTTP end-point from AngularJS

To be honest this is quite a "big question", not because it's difficult or too complicated to explain, but because there are many different ways to do it. The quick answer would be to tell you to use either Angular's native $http service, or ngResource, or the versatile Restangular; and while I can go on and on about those here in this post, I think there has been much better answers on StackOverflow about this topic, for example this one.

Again, I'd personally recommend that you research a bit more on the 3 keywords above. If things still look so murky afterwards, you may always come back here and fire a more detailed question, for example: "How can I make an HTTP request to the server from AngularJS using <NAME>", with <NAME> being $http, ngResource or Restangular, which I (or any other active user) would then be more than happy to answer!

Community
  • 1
  • 1
Khang Dinh
  • 86
  • 1
  • 5
  • What would be the difference between you code and a simple `var content = require('path/to/content.json');` and then create the endpoint `app.get( '/api/v1/content', function ( require, response ) { response.setHeader( 'Content-Type', 'application/json' ); response.json( content ); } );` – Jonathan Solorzano Nov 14 '15 at 19:36
  • `require(...)` is used to declare the use of another nodejs module (as documented [here](https://nodejs.org/api/modules.html#modules_module_filename)) and thus cannot be used to read the content of a file on the filesystem. My code above differs only in that instead of `require`, I used `readFileSync` ! – Khang Dinh Nov 14 '15 at 19:42
  • @JonathanS. indeed it works. Thanks for pointing it out so I'm now aware that there is another way to read json files. However still, `readFile` and `readFileSync` may be better practices as discussed [here](http://stackoverflow.com/a/7165572/3429055), because apparently `require` would cache the content of the file, so when you need to update your json file, you may run into some unnecessary overhead. – Khang Dinh Nov 14 '15 at 19:57
  • I get the following error when using **solution a**: require is not a function – Jonathan Solorzano Nov 14 '15 at 20:11
  • My bad. The `require` statement was masked by the parameter name stated above (from your original code). I changed my original answer so that the parameter is named as `request` instead. Now `require('fs')` should work as expected. Lemme know if it works for you! – Khang Dinh Nov 14 '15 at 20:16
  • It works now, but **solution a** doesn't parse the file, it shows text. – Jonathan Solorzano Nov 14 '15 at 20:18
  • In that case you could wrap everything inside `JSON.parse()`, like here: `response.json( JSON.parse(require('fs').readFileSync('./client/content.json', 'utf8')) );` – Khang Dinh Nov 14 '15 at 20:23