promises in angular - POST request - javascript

I'm new to programming and was wondering why do you not need a promise on a post request, but you do on a get request?
var getAll = function() {
return $http({
method: 'GET',
url: '/api/links'
}).then(function(resp) {
return resp.data;
})
}
var addLink = function(link) {
return $http({
method: 'POST',
url: '/api/links',
data: link
})
//you don't need a promise on a POST!
}

Well, $http always returns a promise on both GET and POST. In your case, you need to do something with the data that comes back from your GET, so you're correctly using the promise's then() to run some code after the HTTP request finishes.
In your POST, it doesn't look like you care about the response, so you're simply choosing not to do anything. You could just as easily tack a then() onto your POST as well for any number of reasons.
Also, promises chain, so then() also returns a promise. Whatever code calls getAll() and addThis() can do something with the promise too. However, something that does getAll().then(function(data) { ... }) will have the data from the HTTP response passed to it because of the return resp.data you have up there.
Code that does addThis().then(function(data) { ... }), in this case, will have the entire HTTP response passed to it since there's nothing processing it like in getAll().

Because when you GET you are going to return a response which generally requires the request to wait for some sort of response. POST you don't necessarily need to wait for a response. As a note, just because you don't "need" a promise on a POST doesn't mean you can't have one. You could add one if you so desire.

Related

window.fetch .then(), not waiting

Using window.fetch() in Firefox and Chrome to get data from a local JSON file, is proving troublesome:
var url = "http://sandbox.ccchapel.com/Thy-Kingdom-Come/data/outreach-spree.json";
var request = new Request(url, {
method: 'get',
mode: 'no-cors'
});
fetch(request).then(function(response) {
console.log(response);
return response.json();
}).then(function(j) {
console.log(j);
});
For whatever reason, the first .then() function is being called prior to the full AJAX response, resulting in promise object (response) being
<state>: "pending"
Which leads to an unwanted output as I'm not getting the data I wanted to get.
I've looked at multiple documents on I can't seem to find anything on my end that I'm doing incorrectly.
Any ideas?
The posted code is fine as it is. Replace the url with
var url =
"data:application/octet-stream;base64,eyJncmVldGluZyI6ICJoZWxsbyBmb2xrcyJ9Cgo=";
({"greeting": "hello folks"}) to see it in action.
What appears to be missing is a .catch clause on the promise chain to report parsing errors in the .json file.
After a bit more Googling, I found this article by Google: https://developers.google.com/web/updates/2015/03/introduction-to-fetch#chaining-promises
Looks like you have to build some extra functions to wait for the status to be resolved. This will then pass the response properly, as you'd expect.

get JSON from a Promise

I am using mocha to test a promise that is written in a separate javascript file. I am trying to send data to the promise with a POST request, although I'm not sure what the url should be. Here's what I have so far, using request-promise:
var rp = require('request-promise');
var options = {
method: 'POST',
url: '/algorithm.js',
body: data,
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(function(body){
count++;
done();
});
The error states that I have an invalid url, although I'm not sure how else to POST to promise inside of a javascript file.
I am trying to send data to the promise with a POST request
You can't do that, at least not directly.
POST requests are for sending data to HTTP servers.
Promises are a JavaScript object for handling asynchronous operations.
These are different things.
algorithm.js needs to either contain code that you can call directly, in which case you should require that code and then call the function.
var algorithm = require("algorithm");
if (algorithm.something()) {
count++;
}
done();
… or it should be server side JavaScript that you need to run an HTTP server for. Once you run the HTTP server, you'll be able to use code like what you wrote in the question, but you'll need to provide an absolute URL since you need to say you are using HTTP and localhost and so on.
var options = {
method: 'POST',
url: 'http://localhost:7878/route/to/algorithm',
body: data,
json: true // Automatically stringifies the body to JSON
};

IE8 changing GET request to POST: Angular $http

I am making call to a REST service from my AngularJS app using $http. The issue is whenever I make a GET request from IE8, it gets converted to POST request. Calls with other http methods (POST,PUT) work fine. This happens only with IE8.
Here is my code
```
var request = {method: method, url: url, data: payload};
var promise = $http(request) .then(function (response) {
return response;
});
```
Can someone please help. I have tried sending different types off data payload : null,undefined,empty object, some object. But nothing worked.
I think I have found the solution. We need to send empty string as payload. Or, use $http.get

Understanding angular's promises

I'm learning Angular but having troubles to understand a point. I want to get data from my server. I used this code (from angular's doc) :
this.myFunction = new function()
{
var uri = this.getServerUri() + "Connexion/"+login+"/"+CryptoJS.MD5(pass);
var promises = $http.get(uri)
.success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
//alert("success:"+JSON.stringify(data));
return data;
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
return "";
});
return promises;
};
But I don't understand the behavior of the success function. When I call this function, it works fine, I get the server's answer but I get the full promises object (I have to write "promises.data" to get my data). Could you explain me why ? Because in the success function I tried to return only the data.
EDIT : I forgot to add my calling function :
var serverAccepted = this.MyFunction().then(function(promise) {
var objet = promise.data;
if(!_.isEmpty(objet))
{
userService.setUser(objet, true);
return "";
}
else return "Error while trying to login on the server";
});
return serverAccepted;
Thank you
A promise is a way of dealing with asynchronous requests without blocking. Instead of waiting for a slow operation (like waiting for the server to respond), before executing any more code, a promise is returned and code execution continues.
As such, when you call myFunction in your code above, it will return a promise object.
The promise then provides some neat methods for registering a callback to run code when the server does respond. These methods are .then() and catch() for the success and error case respectively.
Passing a function as an argument will call that function when the server has responded, and you can do with the data what you like. Take this example:
console.log("About to send request");
myFunction()
.then( function (myData){
console.log("Response received", myData);
})
.catch( function (myError){
console.error("Oh dear", myError);
});
console.log("Request sent!");
This will log the following to the console:
About to send request
Request sent!
Response received, {}
EDIT
In response to your comment:
why does the response received contains the full promise object and not only the data?
Because I return the data in the success function.
The response you receive does not contain a promise at all, but your function returns a promise. In your example serverAccepted is assigned the return value of myFunction() which is a promise and will not change.
The line:
.success(function(data, status, headers, config) {
return data;
})
Doesn't really do anything at all - returning a value from a .then() or .success() function is only useful if you are going to chain several calls to .then() together - it provides a way of manipulating values without an ever increasing pyramid of nested callbacks. Returning a value from within a promise callback (function passed to .then() or .success()) will not change the promise itself (serverAccepted in your case).
For example:
assume http GET some/url on your server returns:
{
foo: 'bar',
dorks: 12
}
When we use $http.get This data is inside the response object as a field called data. Most of the time we don't care much about the rest of the stuff, if the call was successful, we just want the data, so we can return it from the first .then() call (normally inside your service) so that any subsequent .then() calls (e.g. inside a controller) can access the data object directly.
myPromise = $http.get('some/url')
.then( function (response) {
console.log(response); //--> { status: 200, data: { foo:....}}
return response.data;
})
.then( function (data) {
console.log(data); //--> {foo: 'bar', dorks: 12}
return dorks;
})
.then( function (data) {
console.log(data); //--> 12
})
console.log(myPromise); //--> promise object with .then() .catch() etc
// ^ THIS WILL NOT CHANGE.
When I call this function, it works fine, I get the server's answer but I get the full promises object
Sounds like you are doing something like this:
var data = service.myFunction();
Above would be fine in synchronous world, however in case of asynchronous operations this is not correct usage of the promises. Instead you should use returned promise then/success methods:
service.myFunction().then(function(data) {
console.log(data);
});
$http request ,returns a promise with two $http specific methods: success and error. success function waits until request is to be finish with success (that means after $http promise resolves), and error function will execute only after the $http promise is rejected.

Make child Route fire model hook only after the promise returned by parent Route has resolved in EmberJs?

Given the following router, with a fairly straight forward routing synatx:
App.Router.map(function () {
this.resource('foos', function(){
this.resource('foo', { path: '/:foo_id' }, function(){
this.route('bar');
});
});
});
I have FoosController, and FooBarController, with corresponding routes for each: FoosRoute and FooBarRoute.
Both routes have a model hook that returns a promise, which is obtained from ic.ajax.
When I navigate to /foos, and then navigate to /foos/123/bar, the following sequence happens:
FoosRoute#model make XHR request to GET /api/foos
Response returned from /api/foos
FooBarRoute#model makes an XHR request to GET /api/foos/123
Response returned from /api/foos/123
This is great, and my app works fine. Next I naigate directly to /foos/123/bar, the following sequence happens:
FoosRoute#model make XHR request to GET /api/foos
FooBarRoute#model makes an XHR request to GET /api/foos/123
Response returned from /api/foos/123
Response returned from /api/foos
The model hooks for both FoosRoute and FooBarRoute fire in quick succession.
The server takes a longer time to return the response from /api/foos than it does for /api/foos/123, and so they arrive out of order. This puts my app into an incorrect state, and I would like to fix this, by ensuring that the model hook for FooBarRoute is fired only after the promise returned by the model hook for FoosRoute has resolved.
How can I do this?
These JsBins provide a concise demonstration of the problem, forked off the demo put together by #kingpin2k:
Using find. Both models load, but child route loads its model before parent route:
http://jsbin.com/topot/3/edit?html,js,console,output
Using fetch. Both models load, and child route correctly waits for parent route to load model, but UI doesn't update:
http://jsbin.com/topot/4/edit?html,js,console,output
You need to use fetch as we already discussed, and in your custom find overload you need to return the record, not the results of record.load which is undefined.
return App.AppModel.fetch(1);
App.AppModel.adapter = Ember.Adapter.create({
find: function(record, id) {
//instead of jQuery.ajax, use ic.ajax as suggested by stefanpenner
//See: https://github.com/emberjs/ember.js/issues/4442#issuecomment-36207354
var req = ic.ajax.raw({
type: 'GET',
url: App.apiUrl+'/appmodels/'+id,
contentType: 'application/json',
dataType: 'json',
processData: false
});
return req.then(function resolve(result) {
console.log('AppModel adapter find resolve', result.response);
record.load(id, result.response);
return record;
});
}
});
http://jsbin.com/cukuciva/1/edit

Categories

Resources