Today I have had this weird problem where in this function actions.order.capture(), it doesn't fire:
actions.order.capture();
this.props.handlePaymentComplete(data.orderID);
But when I use it like this it works:
actions.order.capture().then(() => {this.props.handlePaymentComplete(data.orderID);})
I understand that in the later case it waits for actions.order.capture() to end, and I would have understood if there was any connection between the result of actions.order.capture and the later function, but they are not dependent on each other's value, and when the second function fired before waiting to the first one to end, the first one doesn't fire at all.
What may be the case?
Looks to me it is asynchronous, .then() is called after the Promise resolved.
You should use the code bellow in an async function :
await actions.order.capture();
this.props.handlePaymentComplete(data.orderID);
Make sure it is in an async function. If not, the function will be called but the program won't stop to wait the answer ... So it will execute everything you wrote then close the process and you'll never get an answer. "await" makes the program wait for the answer, but it must be in an async function like this:
async function () {
await .....
}
Related
I would like to run this code with babel:
redisClientAsync.delAsync('key');
return await someOtherAsyncFunction();
inside an async function without await the first line. is this OK?
how else can I run something that I don't care?
Can I just fire the non-promisified function del('key',null) without a callback?
Yes, you can do that, and it will run the two asynchronous functions in parallel. You've just created a promise and thrown it away.
However, this means that when the promise is rejected you won't notice. You'll just get an unhandledRejection eventually which will crash your process if not handled.
Is this OK? How can I run something that I don't care?
Probably it's not OK. If you truly wouldn't care, you hadn't run it in the first place. So you should be clear and explicit what you care about (and what not):
do you want to wait? (for side effects)
do you need the result?
do you want to catch exceptions?
If you only want to wait and don't care for the result value, you can easily throw away the result:
void (await someAsyncFunction()); // or omit the void keyword,
// doesn't make a difference in an expression statement
If you don't care about exceptions, you can ignore them using
… someAsyncFunction().catch(function ignore() {}) …
You can throw that away, await it, do anything with it.
If you want the result, you have to await it. If you care about exceptions, but don't really want to wait, you may want to execute it in parallel with the following functions:
var [_, res] = await Promise.all([
someAsyncFunction(), // result is ignored, exceptions aren't
someOtherAsyncFunction()
]);
return res;
inside an async function without await the first line. is this OK?
Yes, there are cases where you'd want to do this which are perfectly reasonable. Especially where you don't care about the result - one example is an analytics tracking operation that should not interfere with business critical code.
how else can I run something that I don't care?
In many ways, however simply calling the promise function works. Your del without a callback would probably work in this case but some functions don't guard against not passing callbacks, so you can pass an empty function instead (.del('key', () => {})).
You do want to however make sure that you know about it failing, even if you don't want to disrupt the operation of code - so please consider adding a process.on("unhandledRejection', event handler to explicitly ignore these particular exceptions or suppress them via:
redisClient.delAsync('key').catch(()=>{});
Or preferably, something like:
redisClient.delAsync('key').catch(logErr);
From all the research I've made so far, I think it's fine to do it, as long as you guarantee that the function you are not awaiting for guarantees a way to handle its own errors in case that happens. For example, a try-catch wrapping the whole function body, like you see in the following snippet for the asyncFunction.
It doesn't matter if the function throws synchronously or asynchronously. It guarantees the your mainFunction will complete no matter what. That's the key point here.
If you don't guarantee that, you have to risks:
If it throws synchronously, your main function will not complete.
If it throws asynchronously, you'll get an unhandled excepction
// THIS IS SOME API CALL YOU DON'T WANT TO WAIT FOR
const mockAPI = () => {
console.log("From mockAPI");
return new Promise((resolve,reject) => {
setTimeout(() => reject("LATE THROW: API ERROR"), 500);
});
};
// THIS IS THE SOME ASYNC FUNCTION YOU CALL BUT NOT AWAIT FOR
const asyncFunction = async (syncThrow) => {
try {
console.log("Async function START");
if (syncThrow) throw new Error("EARLY THROW");
await mockAPI();
console.log("Async function DONE");
}
catch(err) {
console.log("From async function catch");
console.log(err.message || err);
return;
}
};
// THIS IS YOUR MAIN FUNCTION
const mainFunction = async (syncThrow) => {
try {
console.clear();
console.log("Main function START");
asyncFunction(syncThrow);
console.log("Main function DONE <<< THAT'S THE IMPORTANT PART");
}
catch(err) {
console.log("THIS WILL NEVER HAPPEN");
console.log(err);
}
};
<div>
<button onClick="mainFunction(true)">Sync throw</button>
<button onClick="mainFunction(false)">Async throw</button>
</div>
Not in Node.js.
Node does not wait for ever-pending Promises. If other tasks are already completed and there is nothing left in the event loop, the Node process will be terminated even though there exists pending promise.
For the following script, if someOtherAsyncFunction() get resolved in 5 seconds, but redisClientAsync.delAsync('key') takes 10 seconds to execute, the Node process will be terminated after 5 seconds in theory, before the first line is resolved.
async function doSomething() {
redisClientAsync.delAsync('key');
return await someOtherAsyncFunction();
}
await doSomething();
For the past 2 days I have been struggling on this thing. I want to watch for changes on particular collection. All of the logic for these changes is in asynchronous way. I tried to make the EventEmitter callback function to be asynchronous but still works in synchronous manner.
Pseudo code example:
const someLogicFunction1 = async () => {
// some logic here
}
const someLogicFunction2 = async () => {
// some logic here
}
const collectionEventEmitter = Collection.watch();
collectionEventEmitter.on('change', async (change) => {
await someLogicFunction1();
await someLogicFunction2(); // has to wait for first function to finish
});
As I explained above I tried this approach but still runs synchronously. The second function usually has to wait for the first function to finish its task in order for the whole code to be properly working.
EDIT:
From what I have found it seems that the callback function firstly gets all this "change" parameter event objects and then executes the code. What I need actually is to execute the code for every "change" event parameter - not for all of them at once.
One solution is to make someLogicFunction1() returning a promise and calling someLogicFunction2(); in then of first function, like this:
await someLogicFunction1()
.then(function(){
someLogicFunction2();
});
You just need to modify someLogicFunction1(); like this:
someLogicFunction1( )
{
return new Promise( async function( resolve, reject ) {
// Do your stuff here
}); // eo promise
}
Don't forget to resolve() in someLogicFunction1 function.
resolve();
You can also reject() in someLogicFunction1 and catch the error when you call this function.
reject();
You can pass an argument to resolve and reject and get it in your call.
I am making an API call and want the code after the call to not run until the API call finishes.
I have a function, this.api_call, which calls an API and returns an array, returnValue, after the API call is complete.
let returnValue = this.api_call(data);
//This line should not run until returnValue has been set
this.otherFunction(returnValue[0], returnValue[1]);
How can I make just that one line wait before running? I want other code to still be able to run before the API call completes, it's just that one line that should wait.
that's where Promises come in, If your function this.api_call(data) returns a Promise, you can then call the then function on it, with a callback, and this callback will be run only after the promise has resolve.
this.api_call(data).then((returnValue) => {
this.otherFunction(returnValue[0], returnValue[1]);
});
You can also use RxJS's observable, which lets you alter your data before returing it using pipe function. If you are using observable, make sure your subscribe to your observable otherwise it will never be fired.
If your this.api_call(data) function is returning an observable ( usually the case if you use Angular), use it like that:
this.api_call(data).subscribe((returnValue) => {
this.otherFunction(returnValue[0], returnValue[1]);
});
There is also a way to use async / await keywords but i'm not a pro in this concept so i'll let somebody else answer that.
There are multiple ways to achieve it, the simplest one is async / await syntax of Promise:
async function myAsyncFunction(): Promise<void> {
let returnValue = await this.api_call(data);
this.otherFunction(returnValue[0], returnValue[1]);
}
this.api_call(data) have to return a Promise<ArrayLike<...>> in your example.
So I tried doing something like this
async function() {
while (x) {
}
// code
}
The reason I want to do this is because I need something to be done only when X becomes false, and I want it to be in another thread so my website is still usable, and according to the naming and what I read about it, async function should be async... It's only natural right?
But instead, my application is completely frozen when the while loop is running. Can someone please explain why this happens and if there's a way around it?
Thank you.
async does not mean multithreading, it just means that you can use the await keyword it it and that the value returned by that function is guaranteed to be a Promise, that its result will always be resolve/rejected in an asynchronous way.
So if the code within the async function does not utilizes any other asynchronous code then it would block the rest of the code the same way as a regular function would do.
If you use await within your while loop, then other code that is waiting could interleave at that point.
async function() {
while (x) {
// ...
await someFunction() // at this `await` other code could be executed
// ...
}
// code
}
So a await in the async function does two things, if the right side of the await is a Promise, then it will wait until it is resolve (or rejected) and it will allow other code that is scheduled to be executed to interleave.
I just wanted to share how I fixed my issue. It might not be the cleanest solution or the right solution, but it did just what I wanted with no performance issues.
All I wanted is to make a while loop that doesn't interrupt my code and at least seems like it runs asynchronously... and the async keyword wasn't what I was hoping it was, and doesn't do anything close to it. Instead, I tried this solution and it worked perfectly.
setTimeout(function() {
while (true) {
if (x) {
break;
}
}
// code
}, 0);
It seems that when you type 0 for the delay in a setTimeout, it executes the function you pass to it only after all of the pending code has executed. And so, it makes it act like it's kind of an async function. It accomplished what I wanted and works seamlessly, so that's what's improtant. If there's a better simple solution, please inform me.
Thank you.
This question is theoretical - I have no concrete problem to solve.
With that said, why does the async keyword wrap the return value of an async function in a promise? What's the point? Is it ONLY because the await expression expects a promise? Or is there some meaning / use behind this decision?
I thought i'd answer this primarily because async in Javascript used to confuse the hell out of me, and all of a sudden it snapped, so i hope this analogy may help this happen for you.
You have an async event. This could be anything, getting something from a server, doing something in the browser that takes time, training a machine learning model (!), executing a function or method that uses a setTimeout etc.
The beauty of Javascript and a key reason it works so well for the browser is that it uses the processor thread it runs on in a very clever way that stops the thread from getting blocked by processes that take time (like the ones mentioned above)
Many other languages, for example Ruby run on more than one thread. It is possible to use service workers to run processes on multiple threads in javascript but that is outside the scope of this answer!
The async nature of the JS event loop allows the thread to 'go off' and do something else while it is waiting for a process to finish.
The problem with this from a programming point of view is that it is possible for something in the code that relies on the result of a blocking event to get 'undefined' as a result of the event if it doesn't wait for the event to finish before it tries to use the result of it. Take this piece of code below
let scopedVariable
console.log('the code has started')
setTimeout(() => {
scopedVariable="I am the result of some async process"
}, 5000);
console.log(scopedVariable)
When the code reaches the console log, the setTimeout hasn't yet completed. As the setTimeout sets the scopedVariable only when it completes, the variable is undefined when we log it
if however
We wrap the timeout in a promise we can await it's resolve callback (first argument of promise) and the code will 'pause' until the promise reaches the resolve callback before continuing.
When we await the promise and the setTimeout completes, the resolve function sets the variable, so that when we console log it it holds the value from the promise
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
const result = await asyncEvent
console.log(scopedVariable)
}
container()
You can use await and .then interchangably
For example we could go:
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
const container = async () => {
asyncEvent.then(() => console.log(scopedVariable))
}
container()
once again the code will pause at .then and then continue when the asyncEvent promise has resolved.
In fact if we use .then we don't need to enclose it in an async function so we can rewrite it like this
let scopedVariable
const asyncEvent = new Promise ((resolve,fail) => {
setTimeout(() => {
resolve(scopedVariable="I have resolved")
}, 5000);
})
asyncEvent.then(() => console.log(scopedVariable))
The great thing about .then is that the accompanying .catch allows you to catch any errors thrown by the async event (for example if retrieving something from a server when there is an error). For async await you need to wrap potentially dangerous functions in a try catch.
In order to use await you need to be inside an async function (hence the async container function above). This is not necessary with .then, but .then and .catch chains can make your code messy.
I hope this helps!
The async and await operators are just syntactic sugar that hide the underlying use of promises to implement asynchronous code.
Using async before a function definition makes the function return a promise that resolves to the function's return value, rather than returning normally.
Using await before an asynchronous function call suspends the current function until the promise that it returns is resolved. It's basically equivalent to wrapping the remainder of the function in an anonymous function, and using that as the .then() callback of the promise.
For more information between the relationship, see How to translate Promise code to async await