I'm aware this is a common problem asked by developers but I can't seem to find anyone who has the same issue as me.
I've got a game i'm creating, this game has lots of factories that when called return a game object, such as a player. Before the game even starts, i need to make sure all the images required are loaded, i did this by simply converting the .onload event into a promise, and placing that into an async function with an await call. However, due to changes in how i'm organizing the game, i will need to handle image loading in those factories that create game objects. This is a problem because now the game doesn't know when all the images are loaded. I thought I might be able to make those factories asynchronous and await on them, they will have an async function call that is also awaited on, but I don't believe this is possible. So abstracted, this is what I want:
I have a promise gotBanana, which resolves once I have gotten my banana.
this is in an async function called, getBananas(), which gets lots of bananas in the loop, it waits for the gotBanana promise to resolve every loop iteration.
I want to put this in another (probably async) function, but I want that function to await for the getBananas() function to finish.
Is it possible to do this or do i need to handle this situation in a different manner?
Maybe you're looking for Promise.all that resolves all promises in parallel and return promise when it will be done. So you just need to map all your assets (images or other) and await it.
Related
I am working on a NestJS API which receives some article codes and saves them in a DB with status as queue and then i want to build a background process which searches for articles with queue status and fetches a website with that code and fills in the information about that article ID.
I want it to fetch codes in 5 parallel routines, each one should get a new code from the list as soon as it finished fetching the current code.
The way it's built right now, it gets 5 codes and uses Promise.all but what i don't like on this approach is that if one of the await is significantly slower than the other, they all way for the slowest one.
const promiseResult = await Promise.all(promiseList);
Which approach is the best one for me to learn in order to achieve what i am planning to do?
Basically you do your job when all the promises are fulfilled. You are correct when you say that you wait for the slowest one, as this is exactly what await Promise.all(promiseList) does.
Now you need to ask yourself the question whether you are able to process the quicker promises while you await for the slowest one. If so, then you can iterate your promises and define a .then() for them:
for (let promise of promiseList) {
promise.then((value) => {
//Do something
});
}
This way all your promises have a then handler for the case when the promise is fulfilled and your Javascript flows normally, without waiting for any of the promises. Once each promise is fulfilled, the event loop will detect that an event happened and call your callback function (in the case of the example above, the arrow function inside the then call).
Note that the then callback should never assume that the other promises were also completed, but that shouldn't be a problem in your case, because you want to work when your promise list was only partially completed as well.
ive found out that its a best practice for nodeJS / ExpressJS as an API-Endpoint for a ReactJS Software to only use asynchornus functions for mysql-querys etc.
But i really dont get how this should work and why it decrease performance if i didnt use it.
Please imagine the following code:
API Endpoint "/user/get/1"
Fetches every datas from user with id one and responds with a json content. If i use async there is no possibility to respond with the information gathered by the query, because its not fulfilled when the function runs to its end.
If i wrap it in a Promise, and wait until its finished its the same like a synchronus function - isnt it?
Please describe for me whats the difference between waiting for a async function or use sync function directly.
Thanks for your help!
If i wrap it in a Promise, and wait until its finished its the same
like a synchronus function - isnt it?
No, it isn't. The difference between synchronous and async functions in JavaScript is precisely that async code is scheduled to run whenever it can instead of immediately, right now. In other words, if you use sync code, your entire Node application will stop everything to grab your data from the database and won't do anything else until it's done. If you use a Promise and async code, instead, while your response won't come until it's done, the rest of the Node app will still continue running while the async code is getting the data, allowing other connections and requests to be made in the meantime.
Using async here isn't about making the one response come faster; it's about allowing other requests to be handled while waiting for that one response.
If you know that the Promise has already been resolved why can't you just call get() on it and receive the value? As opposed to using then(..) with a callback function.
So instead of doing:
promise.then(function(value) {
// do something with value
});
I want to be able to do the much simpler:
var value = promise.get();
Java offers this for it's CompletableFuture and I see no reason why JavaScript couldn't offer the same.
Java's get method "Waits if necessary for this future to complete", i.e. it blocks the current thread. We absolutely never want to do that in JavaScript, which has only one "thread".
It would have been possible to integrate methods in the API to determine synchronously whether and with what results the promise completed, but it's a good thing they didn't. Having only one single method, then, to get results when they are available, makes things a lot easier, safer and more consistent. There's no benefit in writing your own if-pending-then-this-else-that logic, it only opens up possibilities for mistakes. Asynchrony is hard.
Of course it not, because the task will run asynchronously so you can't get result immediately.
But you can use a sync/await to write sequential asynchronous code.
For a couple of years, I was dealing with a part time problem where some DOM elements loaded with jquery html function were not accessible immediately after the function call (The behaviour was a bit like executing a function without waiting for the document ready event). Even though .html() is suppose to be synchronous, this SO answer (and also this one) suggests using the promise of the html function:
$('#divId').html("<h1>hello</h1>").promise().done(function(){
//Callback
});
A promise could make sense in such context but what intrigues me about this promise is that it will also be returned with every jquery's object:
$('#divId').promise().done(function(){
//Will also be called...
});
Since I couldn't find anything about it in the documentation of the html function, I was wondering what was the real purpose of this promise and if it is used correctly in this context.
The two methods are not related. The reason people often suggest this is because someone found out that they could use .promise().done() to make their code that has a race condition work. It worked for the same reason wrapping the same code in setTimeout(fn, 0) would make it work; it pushes it off to the callback queue to be ran later, likely after the browser performs a render or after some other async callback completes.
.html is synchronous, does not have a callback, and does not need a callback. However, the browser's renderer is asynchronous, so it won't render the change until after the callstack is clear. Using .promise pushes the callback off to the callback queue, thus running the code after a render which resolves the race condition or async logic flaw.
.promise() used on a jquery collection returns a promise that will resolve once all currently running jquery animations are complete. If there are no currently running animations, the promise will resolve immediately and the callback will be pushed to the callback queue to be called once the stack is clear.
It's nothing more than a bandaid. I'd suggest not using it, and instead fixing whatever async logic flaw is causing it to be the solution.
I've got this problem that I couldn't find a solution for by googling.
I've got a library, that I'm using (and do not want to edit, unless it's really necessary) that allows the user to select an item, then calls my custom callback function to modify the item and then continues working with it.
I need to perform some asynchronous tasks on it, which may take some time. This creates a race condition as my async tasks have not yet finished when the callback function is finished and the library continues its work on the item.
library.onItemSelectionCallback = function (item) {
myService.modifyItem(item).then(
function (modifiedItemProperty) {
item.newProperty = modifiedItemProperty;
});
myService.anotherModifyItem(item).then(
function (modifiedItemProperty) {
item.existingProperty = modifiedItemProperty;
});
}
How do I wait for both of my async tasks to finish, before allowing this callback to finish?
Only thing I could think of is looping with while and sleep every hundred or so milliseconds until both of the promises have been resolved, but that doesn't seem to be a very good solution.
I understand that this makes async requests quite synchronous and might possibly be detrimental for UX, but do not really see another way out.
EDIT: I know that i'm risking with removing the generic nature of the question and thus making it too localized, I will say that I'm trying to use angular-file-upload module, specifically, trying to mount a custom imageService, that would resize the picture before it's upload. I'm mounting it on the onBeforeUploadItem callback. The idea is that creating the resized image may take a while and that is why I need to return a promise from my imageService, that needs to be resolved before upload.
If modifyItem and anotherModifyItem work independently (that is, one does not rely on the other), you can just pipe them both into $q.all, eg
library.onItemSelectionCallback = function(item) {
var promises = {
newProperty: myService.modifyItem(item),
existingProperty: myService.anotherModifyItem(item)
};
return $q.all(promises).then(function(values) {
return angular.extend(item, values);
});
}
This will return a promise that resolves with item.
For the first part of my question -- Yes, I guess the only way to really wait for those two promises to be resolved would be something with a while and sleep, making them synchronous, which would probably work and not even be that bad (except for the site pausing until the requests are fulfilled), but would make me feel very, very bad about myself as a person and how my actions affect this world.
It is not possible to correctly mix callbacks and promises without hacks afaik.
For the second part of my question -- as per comments of #georgeawg, figured that an AngularJS module that implements HTML5 API and callbacks instead of $http service and promises is not how a good AngularJS module should be implemented, and so I moved towards a different module ng-file-upload, which, even though one could argue is less stylish, does the job very well and in an Angular way (ng-file-upload provides a simple $upload service, that returns a promise. If you want to modify files before upload, suggested way is to simply $watch and catch the moment user drag-drops or selects a file.).