Max Taylor Max Taylor - 27 days ago 17
Node.js Question

Can't call $http.get() more than once

Complete Revision Of Question



Since this question has evolved into something completely different, I figured it would be best if I explained the current situation again from scratch.

I'm trying to create a simple messageboard with Node, Express, MongoDB and Angular.

I have a get and post function, which seem to be working fine on the server side, I get no errors and my data is being added/retrieved to/from the database.

The problem lies with my client-side getMessages() function.

In a normal situation I would like to call getMessages() on the initialization of the website, and after posting a message. But for simplicity I created a button that calls "getMessages()" when pressed.

The first time I press this button, a GET-request is sent out and all my messages are retrieved and displayed in the view.

But when I post a message, and hit the 'get-messages-button' again, no new GET request is being sent out, and the function returns the old list (the one retrieved with the first, and only, GET-request)

I've been stuck on this for 3 days now and I really can't understand what I'm doing wrong. The getMessages() function is being called, but it seems as if it stored the 'response.data' from the first GET request somewhere and immediately returns this same data, without getting the chance to send a new GET request.

Code:



Controller

(function() {
'use strict';

angular
.module('app')
.controller('MainController', mainController);

function mainController(navigationFactory, $http, $timeout, apiFactory, $scope) {

var that = this; // jshint ignore: line

function init() {
//that.getMessages();
}

that.getMessages = function() {
return apiFactory.getMessages().then(function(messages) {
that.messages = messages;

});
}

that.postMessage = function() {

apiFactory.postMessage(that.message).then(function(response) {
console.log('Posted from controller', response);
}).catch(function(e) {
console.log(e);
});

}

init();
}
})();


Service

(function() {
'use strict';

angular
.module('app')
.factory('apiFactory', apiFactory);

function apiFactory($interval, $localStorage, $sessionStorage, $http) {

var factory = {};

factory.postMessage = function(message) {
return $http.post('http://localhost:5000/api/message', {msg: message}).then(function(response) {
return response;
});
}

factory.getMessages = function() {
var promise = $http.get('http://localhost:5000/api/message').then(function(response) {
console.log('data:', result.data); //Immediately returns old list without sending new GET request
return response.data;
});

return promise;
}

return factory;
}

})();


Server.js (Just in case it turns out to be my server-side code anyway)

var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');


var Message = mongoose.model('Message', {
msg: String
});
var app = express();


app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
})

app.get('/api/message', GetMessages);

app.post('/api/message', function(req, res) {
console.log(req.body);

var message = new Message(req.body);
message.save(function(err) {
if(err) {
console.log(err);
} else {
res.status(200).send('Message added');
}
});
})

function GetMessages(req, res) {
console.log('Getting messages from server');
Message.find({}).exec(function(err, result) {
if(err) {
return res.status(500).send(err);
}
return res.status(200).json(result);
});

console.log('Got messages from server');
}

mongoose.connect("mongodb://localhost:27017/mydb", function(err, db) {
if(!err) {
console.log("Connected to mongoDB!");
}
})

var server = app.listen(5000, function() {
console.log('listening on port ', server.address().port);
})


UPDATE



This might probably help in illustrating what exactly the problem is.

I have a function that is called when I press a button on my view:

that.getMessages = function() {
$http.get('http://localhost:5000/api/message'); // <-- Only happens once
console.log('get request sent'); // <-- Gets logged everytime
};


All I'm doing is sending a get request to my server. Nothing with promises yet.
The first time I press my button, I can see a GET request in my debugger networks tab, which has a status of 304 and a response of my array of messages.

Now when I press the button for the 2nd time, no GET request is being sent out. I can log messages so I know my function is being called, but It just seems to ignore my $http.get()...

Answer

Your code gets the messages immediately after you posted the new message. So you have no guarantee that the second request will be processed by the server after the first one. There is a big chance they will be processed concurrently. You need to get the messages after the post has been processed, i.e. when the asynchronous response to the first request has come back.

So, first, you need to be able to know when the post has succeeded. So you need to return the http promise, to know if it's resolved or rejected:

factory.postMessage = function(message) {
    return $http.post('http://localhost:5000/api/message', {msg: message});
}

Then you need to get the messages after a successful post:

that.postMessage = function() {
    apiFactory.postMessage(this.message).then(function() {
        that.getMessages();
    });
}