I am working on an angular project that uses leaflet framework for implementing geocoder. My current requirement is to use geocoder, retrieve the lat,lng from the results and emit them to the parent component which would then trigger an event in the parent component.
But the issue remains that I get the results in an async function and I am not able to emit from inside it, or get the data outside to emit it.
This is the geocoder code I am using:
let grocoder = L.Control.geocoder({
placeholder:"Search",
geocoder: this.mapGeocoder
})
.on('markgeocoder', this.getGeo);
Now I plan on using the value that I get in this.getGeo and send it to the parent component.
FYI sendData is the #output() variable of type emitter.
getGeo(res){
var lat = res.geocode.center.lat
this.sendData.emit(lat);
}
I am pretty unfamiliar with dealing with promises etc. So is there any way I can do this. I know it has something to do with resolving the promise but I am not able to understand how to implement it.
Any help is appreciated, Thanks!!
So if i have understood your question correctly, you are trying to emit an #Output value in an async function. I dont really know what geocoder or so is but with a little research i found an example and i am going to clarify that as good as possible.
public getAddress(query: string) {
return new Promise((resolve, reject) => {
this.geocoder.geocode({ searchText: query }, result => {
if(result.Response.View.length > 0) {
if(result.Response.View[0].Result.length > 0) {
resolve(result.Response.View[0].Result);
} else {
reject({ message: "no results found" });
}
} else {
reject({ message: "no results found" });
}
}, error => {
reject(error);
});
});}
This function returns a promise, like the name says that's an operation which promises you to return a value after something is completed, the thing with an API call as an example is that it needs some time to call the endpoint and receive a response. You can either sleep your program and await it or define what should happen after the process is completed and let the program continue on.
resolve() just fulfills the promise and lets the program excecute the function defined in the then block.
what reject() does should be clear, it just says something went wrong an that can then be catched by the catch block in the then function block.
So now you have defined a promised action and what the promise it self is, now you want to tell the program what to do when the promise is fullfilled, you can then it in your program.
see this :
this.getAddress(this.yourQuery).then(result => {
this.locations = <Array<any>>result;
}, error => {
console.error(error);
});
this then calls the function and lets you program move on, after the promise is fullfilled it will return to the then function block and do whatever you have specified in this case this.locations is assigned the value of the result.
you can then emit the Output value in the then function block because thats not on an async thread anymore. (you cannot bind an angular emitter value in asynchronous function or on a async thread)
i hope that helped to code itself is from : https://developer.here.com/blog/using-the-here-geocoder-api-for-javascript-in-an-angular-application
like i said i don't know the api and the usecase but i hope that explanation clarified how to define a promise and await it.
just ask if you have questions, i am not a pro with that to i cant just explain the surface functionality.
i can also recommend this video : https://www.youtube.com/watch?v=vn3tm0quoqE&t=194s. he does great short little videos for such things.
hope that has helped.
Related
I know that very similar questions have been asked, but I can't find one that fits my issue exactly- feel free to point me that way if there is one.
sendSteamAuthTicket: () => {
return new Promise((resolve, reject) => {
greenworks.getAuthSessionTicket(function(ticket) {
console.log('Successfully retrieved Steam API User Auth Ticket.')
console.log(ticket.ticket.toString('hex'))
resolve(ticket.ticket.toString('hex'))
}, function(e) { throw e })
})
}
Basically, this returns an endlessly pending Promise, leading me to believe I can't resolve a Promise from within a nested callback like this. Unfortunately, I can't send the data via an additional function because electron won't let you interface with the browser that way.
Is it possible to do what I'm trying to do here? e.g. more or less obtain a delayed Promise value within this single function?
Alright, I figured it out- sorry for the redundant question, I've been banging my head on this for a few hours. Hearing that the Promise syntax was correct was apparently enough to get it through.
The greenworks package was being imported incorrectly (or, rather, correctly- according to their docs- but needed a direct file path)
It's a little outdated so I wasn't sure why at first.
There's nothing wrong with the way that you're calling resolve. If the callback is called, resolve will be, too, unless ticket is null or similar. My guess would be that greenworks is calling the error callback and then not re-throwing your thrown error. Try doing reject(e) instead of throw e.
I've created a code snippet here that fetches data about a certain country using REST Countries API. The function works fine, and returns a pending promise. That promise's fulfilled value will equal an object containing key value pairs for the country's capital, name, and code.
But if I wanted to use them for something, why wouldn't I just set that very same object equal to a variable and continue to program new actions inside my async function? Why bother trying to use values gained asynchronously on the global scope?
function getJSON(url, errorMSG = 'Something went wrong') {
// feed it the fetch URL, then your customized error message
return fetch(url).then(response => {
if (!response.ok) throw new Error(errorMSG);
return response.json();
});
}
async function countryData(nation) {
try {
const info = await getJSON(
`https://restcountries.eu/rest/v2/name/${nation}?fullText=true`,
'Invalid country selected'
);
return {
// Fullfilled value of promise
capital: info[0].capital,
name: info[0].name,
code: info[0].cioc,
};
} catch (err) {
console.error(err); // display your custom error message
}
}
console.log(countryData('Canada'));
fetch is an async function. Why do they resolve the promise to a response object, instead of continuing to run extra actions once they have it? Because they don't know what you want to do with it. It would be impossible for fetch to handle every possible thing that should happen next, so it just has a single job: get the data, then return it (in a promise). You can then combine this with whatever other code you like.
On a smaller scale, this may happen with countryData too. You might have 10 different parts of your app that want to do things with the result from countryData. It may not be "impossible" for countryData to implement all 10 things, but it's definitely impractical and not a good idea. Instead, countryData can be written to have one job: get the country data and return it. Then each of the 10 pieces of code can do their own things with the result.
This isn't about it being async, the same principles apply to synchronous code to. If you can keep code focused on a single task, without entangling it with the needs of other pieces of code, then your code becomes easier to maintain.
Due to asynchronous Ajax call we are using promise, So that other JS waiting for Ajax success object can access its updated property.
We've 300 JS which will call this promise, Do we've any constraint if so many JS will call promise, it might start pending or never resolved.
Please advise
Thanks in advance
(function () {
window.myObject = window.myObject || {};
let isProfileUpdated = false;
myObject.waitforProfile = new Promise(function (resolve, reject) {
let maxTry = 50;
let currentTry = 0;
let tryForProfile = function () {
if (currentTry < maxTry && isProfileUpdated) {
resolve();
} else if (currentTry < maxTry) {
currentTry++;
setTimeout(tryForProfile, 350);
}
else {
reject('profile never resolved');
}
}
tryForProfile();
});
$.ajax({
url: 'www.google.com',
async: true,
success: function (result) {
result = result.model;
if (result != undefined) {
window.myObject.title = result.title
isProfileUpdated = true;
}
}
});
})();
Caller - We have so many callers dependent on MyObject properties
function initalizeNavigation() {
if (myObject.title !== "") {
createAuthenicatedUtilityNav();
} else {
createSignedOutUtilityNav();
}
}
myObject.waitforProfile(initalizeNavigation)
.catch(function (message) {
console.log(message)
});
There several errors in the algorithm the code was written to follow. Program design needs to fixed before throwing out the code and replacing it. One design approach may be to
Create a global Promise object to be fulfilled with the user profile requested from the server in the ajax call is received at the front end. Call it, say, profilePromise.
Issue an ajax call to obtain the user profile. If it succeeds, resolve profilePromisewith the decoded profile object. If it fails, rejectprofilePromise` with the notified error or error message.
Add a catch handler to profilePromise to inform the user to try again later (or whatever) if it becomes rejected. The posted code doesn't retry the server call so I haven't tried to include it here.
Set up a timeout to reject profilePromise if too much time has elapsed. If the timer calls back attempts to reject the promise after the ajax call has succeeded and fulfilled the promise, rejecting the promise is simply ignored - settled promise state and values are immutable.
The 300+ code points throughout the code can await profilePromise to get the user profile or, alternatively, call profilePromise.then with a fulfillment handler to be called with the profile object after it arrives.
The code points must process profile data in an async function by using syntax similar to
const profile = await profilePromise;
or add a fulfillment handler to process the data using syntax similar to
profilePromise.then( profile => { do specific thing with profile data});
What you cannot do is "call" the promise as if it were a function to get the profile, or make a synchronous function that magically returns profile data before it arrives back from the server.
Put error checking in the .catch handler added in step 3. There is no need to recheck throughout the code - the fulfillment handlers will never get called.
A totally different approach might be tp ensure critical parts of application code don't execute before the profile data has been obtained and placed in a global variable.
In a single page app this might involve modal overlays or hidden sections of HTML that prevent user interaction with the code before being allowed to do so.
Please research the use of async functions and the await operator, or adding fulfillment handlers to a promise using its then method if unfamiliar with them.
What is the best way to determine if the subscriber has finished executing or better yet return something and catch it up-stream? For example:
this._subscriptions.push(this._client
.getCommandStream(this._command) // Returns an IObservable from a Subject stream
.subscribe(msg => {
// Do some processing maybe some promise stuff
http.request(url).then(
// some more stuff
);
});
What's the best know to determine that subscription has finished. I've implemented it as follows:
this._subscriptions.push(this._client
.getCommandStream(this._command)
.subscribe(msg => {
// Do some processing maybe some promise stuff
http.request(url).then(re => {
// some more stuff
msg.done()
}).catch(err => msg.done(err));
});
i.e. added a done method to the object being passed in to determine if this is finished. The issue with that is I'll have to call done in every promise or catch block and find that a little too exhaustive. Is there a cleaner and more automated way of doing this?
I think the examples I've given are not good enough. This implementation is using RX to build an internal messaging bus. The get command stream is actually returning a read-only channel (as an Observable) to get commands and process them. Now the processing could be a http request followed by many other things or just an if statement.
this._client
.getCommandStream(this._command) // Returns an IObservable from a Subject stream
.subscribe(msg => {
// Do some processing maybe some promise stuff
http.request(url).then({
// some more stuff
}).then({
// Here I wanna do some file io
if(x) {
file.read('path', (content) => {
msg.reply(content);
msg.done();
});
} else {
// Or maybe not do a file io or maybe even do some image processing
msg.reply("pong");
msg.done()
}
});
});
I feel like this is a fine usage of the Observable pattern as this is exactly a sequence of commands coming in and this logic would like to act on them. The question is notice msg.done() being called all over the place. I want to know what is the best way to limit that call and know when the entire thing is done. Another option is to wrap it all in a Promise but then again what's the difference between resolve or msg.done()?
Actually, making another asynchronous request inside subscribe() isn't recommended because it just makes things more complicated and using Rx in this way doesn't help you make your code more understandable.
Since you need to make a request to a remote service that returns a PRomise you can merge it into the chain:
this._subscriptions.push(this._client
.getCommandStream(this._command)
.concatMap(msg => http.request(url))
.subscribe(...)
Also the 3rd parameter to subscribe is a callback that is called when the source Observable completes.
You can also add your own teardown logic when the chain is being disposed. This is called after the complete callback in subscribe(...) is called:
const subscription = this._subscriptions.push(this._client
...
.subscribe(...)
subscription.add(() => doWhatever())
Btw, this is equivalent to using the finally() operator.
As per RxJs subscribe method documentation, the last Argument is completed function
var source = Rx.Observable.range(0, 3)
var subscription = source.subscribe(
function (x) {
console.log('Next: %s', x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
please refer this documentation
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/subscribe.md
I have a situation where my WinJS app wants to call a function which may or may not be async (e.g. in one situation I need to load some data from a file (async) but at other times I can load from a cache syncronously).
Having a look through the docs I though I could wrap the conditional logic in a promise like:
A)
return new WinJS.Promise(function() { // mystuff });
or possibly use 'as' like this:
B)
return WinJS.Promise.as(function() { // mystuff });
The problem is that when I call this function, which I'm doing from the ready() function of my first page like this:
WinJS.UI.Pages.define("/pages/home/home.html", {
ready: function () {
Data.Survey.init().done(function (result) {
// do some stuff with 'result'
});
}
});
When it is written like 'A' it never hits my done() call.
Or if I call it when it's written like 'B', it executes the code inside my done() instantly, before the promise is resolved. It also looks from the value of result, that it has just been set to the content of my init() function, rather than being wrapped up in a promise.
It feels like I'm doing something quite basically wrong here, but I'm unsure where to start looking.
If it's any help, this is a slimmed down version of my init() function:
function init() {
return new WinJS.Promise(function() {
if (app.context.isFirstRun) {
app.surveyController.initialiseSurveysAsync().then(function (result) {
return new WinJS.Binding.List(result.surveys);
});
} else {
var data = app.surveyController.getSurveys();
return new WinJS.Binding.List(data);
}
});
}
Does anyone have any thoughts on this one? I don't believe the 'may or may not be async' is the issue here, I believe the promise setup isn't doing what I'd expect. Can anyone see anything obviously wrong here? Any feedback greatly appreciated.
Generally speaking, if you're doing file I/O in your full init routine, those APIs return promises themselves, in which case you want to return one of those promises or a promise from one of the .then methods.
WinJS.Promise.as, on the other hand, is meant to wrap a value in a promise. But let me explain more fully.
First, read the documentation for the WinJS.Promise constructor carefully. Like many others, you're mistakenly assuming that you just wrap a piece of code in the promise and voila! it is async. This is not the case. The function that you pass to the constructor is an initializer that receives three arguments: a completeDispatcher function, an errorDispatcher function, and a progressDispatcher function, as I like to call them.
For the promise to ever complete with success, complete with an error, or report progress, it is necessary for the rest of the code in the initializer to eventually call one of the dispatchers. These dispatchers, inside the promise, then loop through and call any complete/error/progress methods that have been given to that promise's then or done methods. Therefore, if you don't call a dispatcher at all, there is no completion, and this is exactly the behavior you're seeing.
Using WinJS.Promise.as is similar in that it wraps a value inside a promise. In your case, if you pass a function to WinJS.promise.as, what you'll get is a promise that's fulfilled with that function value as a result. You do not get async execution of the function.
To achieve async behavior you must either use setTimeout/setInterval (or the WinJS scheduler in Windows 8.1) to do async work on the UI thread, or use a web worker for a background thread and tie its completion (via a postMessage) into a promise.
Here's a complete example of creating a promise using the constructor, handling complete, error, and progress cases (as well as cancellation):
function calculateIntegerSum(max, step) {
if (max < 1 || step < 1) {
var err = new WinJS.ErrorFromName("calculateIntegerSum", "max and step must be 1 or greater");
return WinJS.Promise.wrapError(err);
}
var _cancel = false;
//The WinJS.Promise constructor's argument is a function that receives
//dispatchers for completed, error, and progress cases.
return new WinJS.Promise(function (completeDispatch, errorDispatch, progressDispatch) {
var sum = 0;
function iterate(args) {
for (var i = args.start; i < args.end; i++) {
sum += i;
};
//If for some reason there was an error, create the error with WinJS.ErrorFromName
//and pass to errorDispatch
if (false /* replace with any necessary error check -- we don’t have any here */) {
errorDispatch(new WinJS.ErrorFromName("calculateIntegerSum", "error occurred"));
}
if (i >= max) {
//Complete--dispatch results to completed handlers
completeDispatch(sum);
} else {
//Dispatch intermediate results to progress handlers
progressDispatch(sum);
//Interrupt the operation if canceled
if (!_cancel) {
setImmediate(iterate, { start: args.end, end: Math.min(args.end + step, max) });
}
}
}
setImmediate(iterate, { start: 0, end: Math.min(step, max) });
},
//Cancellation function
function () {
_cancel = true;
});
}
This comes from Appendix A ("Demystifying Promises") of my free ebook, Programming Windows Store Apps in HTML, CSS, and JavaScript, Second Edition (in preview), see http://aka.ms/BrockschmidtBook2.
You would, in your case, put your data initialization code in the place of the iterate function, and perhaps call it from within a setImmediate. I encourage you to also look at the WinJS scheduler API that would let you set the priority for the work on the UI thread.
In short, it's essential to understand that new WinJS.Promise and WinJS.Promise.as do not in themselves create async behavior, as promises themselves are just a calling convention around "results to be delivered later" that has nothing inherently to do with async.