hi i am having the same probem as here Return address from Google Maps Geocoder v3 , i dont understand how to set my global variable to the return vlaue
i got this at the moment where b returns undefined
var a;
var b;
function outputGeo(result){
b = result;
}
geocoder.geocode({'latLng': event.latLng},function(results, status) {
a = results[1].formatted_address;
outputGeo(a);
});
alert(b);
geocoder.geocode is an asynchronous function because it's performing a JSONP request. In other words, before the results have come back, the alert(b) line is already being called. You need to put that alert line into the callback function after outputGeo(a).
Javascript's a funny language. This async thing bit me until I researched JSONP and the synchrony of Javascript. I suggest you do the same. A great way to learn about this is to write a JSONP-request wrapper of your own. (Just a thought.)
Related
I'm developing a REST server in Play with Scala, that at some point needs to request data at one or more other web services. Based on the responses from these services the server must compose a unified result to use later on.
Example:
Event C on www.someplace.com needs to be executed. In order to execute Event C, Event A on www.anotherplace.com and Event B on www.athirdplace.com must also be executed.
Event C has a Seq(www.anotherplace.com, www.athirdplace.com) from which I would like to iterate and send a WS request to each URL respectively to check wether B and C are executed.
It is assumed that a GET to these URLs returns either true or false
How do I collect the responses from each request (preferably combined to a list) and assert that each response is equal to true?
EDIT: An event may contain an arbitrary number of URL's. So I cant know beforehand how many WS requests i need to send.
Short Answer
You can use sequence method available on Future object.
For example:
import scala.concurrent.Future
val urls = Seq("www.anotherplace.com", "www.athirdplace.com")
val requests = urls.map(WS.url)
val futureResponses = Future.sequence(requests.map(_.get()))
Aggregated Future
Note that the type of futureResponses will be Future[Seq[WSResponse]]. Now you can work on the results:
futureResponses.map { responses =>
responses.map { response =>
val body = response.body
// do something with response body
}
}
More Details
From ScalaDocs of sequence method:
Transforms a TraversableOnce[Future[A]] into a
Future[TraversableOnce[A]]. Useful for reducing many Futures into a
single Future.
Note that if any of the Futures you pass to sequence fails, the resulting Future will be failed as well. Only when all Futures are completed successfully the result will complete successfully. This is good for some purposes, especially if you want to send requests at the same time, no one after another.
Have a look at the documentation and see if you can get their example to work.
Try something like this:
val futureResponse: Future[WSResponse] = for {
responseOne <- WS.url(urlOne).get()
responseTwo <- WS.url(responseOne.body).get()
responseThree <- WS.url(responseTwo.body).get()
} yield responseOne && responseTwo && responseThree
You probably need to parse the response of your WebService since they (probably) won't return booleans, but you'll get the idea.
I have a application with a Django backend and an AngularJS front-end.
I use the angular-gettext plugin along with Grunt to handle translations.
The thing is, I sometimes received dynamic strings from my backend through the API. For instance a MySQL error about a foreign key constraint or duplicate key entry.
How can I add this strings to the .pot file or non harcoded string in general ?
I've tried to following but of course it cannot work :
angular.module('app').factory('HttpInterceptor', ['$q', '$injector', '$rootScope', '$cookieStore', 'gettext', function ($q, $injector, $rootScope, $cookieStore, gettext) {
responseError: function (rejection) {
gettext('static string'); //it works
gettext(rejection.data.error); //does not work
$rootScope.$emit('errorModal', rejection.data);
}
// Return the promise rejection.
return $q.reject(rejection);
}
};
}]);
})();
One solution I could think of would be to write every dynamic strings into a JSON object. Send this json to server and from there, write a static file containing these strings so gettext can extract them.
What do you suggest ?
I also use angular-gettext and have strings returned from the server that need to be translated. We did not like the idea of having a separate translation system for those messages so we send them over in the default language like normal.
To allow this to work we did two things. We created a function in our backend which we can call to retrieve all the possible strings to translate. In our case it's mainly static data that only changes once in a while. Ideally this would be automated but it's fine for now.
That list is formatted properly through code into html with the translate tag. This file is not deployed, it is just there to allow the extraction task to find the strings.
Secondly we created a filter to do the translation on the interpolated value, so instead of translating {{foo}} it will translate the word bar if that's was the value of foo. We called this postTranslate and it's a simple:
angular
.module('app')
.filter('postTranslate', ['gettextCatalog', function (gettextCatalog) {
return function (s) {
return gettextCatalog.getString(s);
};
}]);
As for things that are not in the database we have another file for those where we manually put them in. So your error messages may go here.
If errors are all you are worried about though, you may rather consider not showing all the error messages directly and instead determine what user friendly error message to show. That user friendly error message is in the front end and therefore circumvents all of this other headache :)
I started having a look into Facebook API today. I couldn' say enough how ugly and totally unintuitive it is, at least its Javascript implementation. Anyway, here's the two things I found:
a. I struggled whole day getting 'undefined' messages after properly loggin and getting an access_toekn, now when I tried to write response.first_name after calling FB.api ('/me') I got 'undefined' messages..... Well, I burnt my brain until I got someone here in stackoverflow that said the access token should HAVE to be passed in the call! But you can't find THIS CLEARLY specified in the FB official documentation, it's not even mentioned, not even parameter is shown. So this works:
FB.api('/me', {access_token: taccesstokenvalue}, function(response) {
alert(response.first_name); });
b. now, if I change alert() by document.write() , well, it just does nothing.
c. console.log() never worked out, I Tried on chrome, firefox, opera. Nothing
Why can't I use document.write? I need to verbosely write a lot of things coming out from the API, how can I do it ?
Thanks!!
Well, I found out a solution I think. Hope it helps other people...
I solved it this way:
a. create a form on top of the body area, with hidden field called hAPIresponse and hAccessToken
b. instead of trying to dump the API response right inside the function() as in the code above, fill the hidden fields with what the API returns, concatenating fields one after another if needed, like this:
FB.api('/me', {access_token: taccesstokenvalue}, function(response) {
document.getElementById("hAPIresponse").value="first name:" + response.first_name;
document.getElementById("hAccessToken").value="access token:" + taccesstokenvalue;
});
*here I didn't concatenate anything, just got the first_name property from the API
c. taccesstokenvalue variable comes from previously retrieving it from the URL or you can retrieve it directly through the API. Here comes the manual approach:
function Mid(str, start, len)
{
// Make sure start and len are within proper bounds
if (start < 0 || len < 0) return "";
var iEnd, iLen = String(str).length;
if (start + len > iLen)
iEnd = iLen;
else
iEnd = start + len;
return String(str).substring(start,iEnd);
}
var taccesstoken=window.location.href;
var tvecaux=taccesstoken.split('access_token=');
var taccesstokenvalue=Mid(tvecaux[1],0, tvecaux[1].indexOf('&',0) );
As far as I saw, when you get into the FB.api() call the code CONTINUES TO EXECUTE below the FB.API() call and not through the function(response). This one is triggered asynchronously by its own will, when it thinks it's better to finish :) It seems it's so complicated for FB developers adding a sync=true/false property in the FB.Init() so people used to sync coding won't pull their hairs out of their heads as I did..
Hope it helps somebody, I spent nearly 36 hours trying to do something so simple and stupid like calling an API and retrieving a value from it...
Again, this API couldn't be less intuitive, I can't say it enough. I can't imagine what I will find when trying to pull coments to FB Post replies or even trying to interact with the FB chat
I have a piece of code which makes multiple nested calls to FB.api to retrieve certain information. Eventually, it creates an object called "myfriends" and stores my desired information in that object.
What I want to do is to use that object, after it is filled in with data (i.e. after all asynch calls are done), to run something else. In other words, I need a way for my code to know that those calls are complete. How can I do that?
call 'myfriends' after async request has completed.
Example:
FB.api('/me', function(response) {
alert('Your name is ' + response.name);
// Use 'myfriends' object here
});
I ended up using callback functions. The other problem I had was that my inner API call was in a loop; I ended up using an asynchronous looping function. This combination solved my problem.
I'm looking at implementing Model.sync.deleteRecord() for use with Ember-Data Basic Adaptor.
According to the docs, adapter must call didDeleteRecord() once record has been successfully deleted from the server.
However, I can't find good example on how to actually call didDeleteRecord(). After looking at the source, the best I come up with this:
deleteRecord: function(record, process) {
my_api.remove(record.get('id')).then(function() {
var r = process(record);
r.store.adapter.didDeleteRecord(r.store, r.type, r.record);
});
}
Is there any better, less uglier ways to call didDeleteRecord()?