My goal is to generate an array of Promises dynamically (by using Array.map()), and execute them at a posterior time.
export const ExecuteReader = async () => {
let strAll = [1, 2].map((num) => testingFunction (num))
//await Promise.all(strAll)
}
export const testingFunction = (num) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('I have been called');
resolve(1)
}, 1000)
})
}
ExecuteReader function is called by a "OnPress" event. (React-Native Touchable opacity.)
<TouchableOpacity
onPress={async () => {
await ExecuteReader().catch(err => console.log(err));
}}>
<Text>Click Me</Text>
</TouchableOpacity>
To my understanding, the strAll Promise array should not execute its underlying functions, until it has been awaited ("Promise.All")
Im my case, it seems that the "testingFunction" prints out to console, while the "map" is iterating.
Your help is appreciated.
To my understanding, the strAll Promise array should not execute its underlying functions, until it has been awaited ("Promise.All")
That's incorrect, but you're not alone — it's a common misunderstanding. :-) Promises don't do anything, they're a way to observe and report on the completion of something else. When you call new Promise, the function you pass into it (the promise executor) is called right away, synchronously, to start the operation. Observing the promise via then, catch, etc. (directly or indirectly through Promise.all) doesn't make anything happen, it just hooks up handlers that will be called when whatever is already happening finishes (or if it's already done, will be called almost immediately [but still asynchronously]).
If you want to start those processes later, you need to delay your calls to testingFunction, since calling it starts the timer immediately.
Related
So I'm currently learning about promises in JavaScript, and I tried making my first promise and realized that it ran the setTimeout() even if I didn't call the promise to begin with, just by defining it, it ran by itself. This being postLogin.
const postLogin = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Token: 1234")
}, 2000);
});
^ This logs out "Token: 1234" without calling postLogin.then()
Where as this doesn't run until I call postLogin1.then(token => {console.log(token)});
const postLogin1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Token1: 1234");
}, 2000);
});
postLogin1.then(token => {console.log(token)});
Why is it that if I don't add "resolve" it runs the code without invoking it?
Promise constructors call the function you pass to them immediately. This is the case in both your examples.
If you have console.log inside that function, then it will call console.log. If you don't, then it won't. That's the key difference between the examples.
The then method just adds an event handler that will be called when the promise is resolved (or immediately if it has already been resolved).
If you have console.log in the then handler, then it will be called then the function resolves.
If you don't ever call resolve then it will never resolve. The function you pass to it is still called.
To profile my app more detailed I need to know which promises not awaited but... js not provide such ability.
In python every time when result of async function is not awaited it prints warring
But how to obtain such result in js?
I concluded to do so I have to know few things:
how to override promise construction (to add state field which will show is promise awaited and to set timeout to check state)
what triggered when object awaited (to change state)
I figured out via Proxy that when awaiting, object's then property is called:
async function test(obj) {
await obj
}
test(new Proxy(new Object(), {
get(obj, name) {
console.log("get " + name)
}
})
But actually, as turned out, it happens only with non-promise objects
So when I tried to do this:
Promise.prototype.then = function() {
console.log("called then")
}
test(Promise.resolve({}))
I got nothing in output.
Same things with Promise.prototype.constructor and Promise.resolve:
let getOne = async () => 1
getOne()
getOne neither call Promise constructor nor Promise.resolve.
So what I'm doing wrong ?
How actually async/await creates promises and fetch value from them under the hood, and how can it be overridden ?
I figured out via Proxy that when awaiting, object's then property is called
Indeed, that is correct.
when I tried to do [...] test(Promise.resolve({})) I got nothing in output.
That is because in this code -- contrary to your earlier test with await -- you do not execute an await or a then call here. You just construct a promise, and your proxy object is not trapping the creation of a promise, only the execution of the then method.
This brings us back to your first bullet point:
how to override promise construction?
You cannot.
We have access to the Promise constructor, but there is no way you can trap its execution. If you would make a proxy for it -- with a construct handler -- it would not be called, as the JavaScript engine will still refer to the original Promise constructor when -- for instance -- an async function is executed. So you are without hope here.
I don't believe overriding is something you want. Usually async is telling node that this function is asynchronious and if you have something in the event loop that is "long" procedure such as querying another API or reading IO then those functions will yield promises. You can also try using the following:
return new Promise((resolve, reject) => {... do stuff and call resolve() or reject() based on the expected output})
The returned value will be a promise.
To handle the promise you will need to await it.
To get promise from
let getOne = async () => 1 you will need to make it
let getOne = async () => return new Promise((resolve, reject) => return resolve(1))
To obtain the value later you will need to call await getOne()
I have been reading up on methods to implement a polling function and found a great article on https://davidwalsh.name/javascript-polling. Now using a setTimeout rather than setInterval to poll makes a log of sense, especially with an API that I have no control over and has shown to have varying response times.
So I tried to implement such a solution in my own code in order to challenge my understanding of callbacks, promises and the event loop. I have followed guidance outlined in the post to avoid any anti-patterns Is this a "Deferred Antipattern"? and to ensure promise resolution before a .then() promise resolve before inner promise resolved and this is where I am getting stuck. I have put some code together to simulate the scenario so I can highlight the issues.
My hypothetical scenario is this:
I have an API call to a server which responds with a userID. I then use that userID to make a request to another database server which returns a set of data that carries out some machine learning processing that can take several minutes.
Due to the latency, the task is put onto a task queue and once it is complete it updates a NoSql database entry with from isComplete: false to isComplete: true. This means that we then need to poll the database every n seconds until we get a response indicating isComplete: true and then we cease the polling. I understand there are a number of solutions to polling an api but I have yet to see one involving promises, conditional polling, and not following some of the anti-patterns mentioned in the previously linked post. If I have missed anything and this is a repeat I do apologize in advance.
So far the process is outlined by the code below:
let state = false;
const userIdApi = () => {
return new Promise((res, rej) => {
console.log("userIdApi");
const userId = "uid123";
setTimeout(()=> res(userId), 2000)
})
}
const startProcessingTaskApi = userIdApi().then(result => {
return new Promise((res, rej) => {
console.log("startProcessingTaskApi");
const msg = "Task submitted";
setTimeout(()=> res(msg), 2000)
})
})
const pollDatabase = (userId) => {
return new Promise((res, rej) => {
console.log("Polling databse with " + userId)
setTimeout(()=> res(true), 2000)
})
}
Promise.all([userIdApi(), startProcessingTaskApi])
.then(([resultsuserIdApi, resultsStartProcessingTaskApi]) => {
const id = setTimeout(function poll(resultsuserIdApi){
console.log(resultsuserIdApi)
return pollDatabase(resultsuserIdApi)
.then(res=> {
state = res
if (state === true){
clearTimeout(id);
return;
}
setTimeout(poll, 2000, resultsuserIdApi);
})
},2000)
})
I have a question that relates to this code as it is failing to carry out the polling as I need:
I saw in the accepted answer of the post How do I access previous promise results in a .then() chain? that one should "Break the chain" to avoid huge chains of .then() statements. I followed the guidance and it seemed to do the trick (before adding the polling), however, when I console logged out every line it seems that userIdApi is executed twice; once where it is used in the startProcessingTaskApi definition and then in the Promise.all line.
Is this a known occurrence? It makes sense why it happens I am just wondering why this is fine to send two requests to execute the same promise, or if there is a way to perhaps prevent the first request from happening and restrict the function execution to the Promise.all statement?
I am fairly new to Javascript having come from Python so any pointers on where I may be missing some knowledge to be able to get this seemingly simple task working would be greatly appreciated.
I think you're almost there, it seems you're just struggling with the asynchronous nature of javascript. Using promises is definitely the way to go here and understanding how to chain them together is key to implementing your use case.
I would start by implementing a single method that wraps setTimeout to simplify things down.
function delay(millis) {
return new Promise((resolve) => setTimeout(resolve, millis));
}
Then you can re-implement the "API" methods using the delay function.
const userIdApi = () => {
return delay(2000).then(() => "uid123");
};
// Make userId an argument to this method (like pollDatabase) so we don't need to get it twice.
const startProcessingTaskApi = (userId) => {
return delay(2000).then(() => "Task submitted");
};
const pollDatabase = (userId) => {
return delay(2000).then(() => true);
};
You can continue polling the database by simply chaining another promise in the chain when your condition is not met.
function pollUntilComplete(userId) {
return pollDatabase(userId).then((result) => {
if (!result) {
// Result is not ready yet, chain another database polling promise.
return pollUntilComplete(userId);
}
});
}
Then you can put everything together to implement your use case.
userIdApi().then((userId) => {
// Add task processing to the promise chain.
return startProcessingTaskApi(userId).then(() => {
// Add database polling to the promise chain.
return pollUntilComplete(userId);
});
}).then(() => {
// Everything is done at this point.
console.log('done');
}).catch((err) => {
// An error occurred at some point in the promise chain.
console.error(err);
});
This becomes a lot easier if you're able to actually use the async and await keywords.
Using the same delay function as in Jake's answer:
async function doItAll(userID) {
await startTaskProcessingApi(userID);
while (true) {
if (await pollDatabase(userID)) break;
}
}
I have a simple code in JavaScript that execute a request in an API and return the response, simple. But in this case I will have thousands of requests. So, which one of the code options will perform better, and why. Also which one is recommended as good pratices these days?
First options is using the .then to resolve the promises and the seccond one is using async / await.
In my tests the two options had very similar results without significant differences, but I'm not sure in scale.
// Using then
doSomething(payload) {
const url = 'https://link-here/consultas';
return this.axios.get(url, {
params: {
token: payload.token,
chave: payload.chave,
},
}).then(resp => resp.data);
}
// Using Async / await
async doSomething(payload) {
const url = 'https://link-here/consultas';
const resp = await this.axios.get(url, {
params: {
token: payload.token,
chave: payload.chave,
},
});
return resp.data;
}
Any explanation will be of great value.
From a performance point of view, await is just an internal version of .then() (doing basically the same thing). The reason to choose one over the other doesn't really have to do with performance, but has to do with desired coding style or coding convenience. Certainly, the interpreter has a few more opportunities to optimize things internally with await, but its unlikely that should be how you decide which to use. If all else was equal, I would choose await for the reason cited above. But, I'd first choose which made the code simpler to write and understand and maintain and test.
Used properly, await can often save you a bunch of lines of code making your code simpler to read, test and maintain. That's why it was invented.
There's no meaningful difference between the two versions of your code. Both achieve the same result when the axios call is successful or has an error.
Where await could make more of a convenience difference is if you had multiple successive asynchronous calls that needed to be serialized. Then, rather than bracketing them each inside a .then() handler to chain them properly, you could just use await and have simpler looking code.
A common mistake with both await and .then() is to forget proper error handling. If your error handling desire in this function is to just return the rejected promise, then both of your versions do that identically. But, if you have multiple async calls in a row and you want to do anything more complex than just returning the first rejection, then the error handling techniques for await and .then()/.catch() are quite different and which seems simpler will depend upon the situation.
There should be some corrections in this thread. await and .then are going to give very different results, and should be used for different reasons.
await will WAIT for something, and then continue to the next line. It's also the simpler of the two because it behaves mechanically more like synchronous behavior. You do step #1, wait, and then continue.
console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");
.then splits off from the original call and starts operating within its own scope, and will update at a time the original scope cannot predict. If we can put semantics aside for a moment, it's "more asynchronous," because it leaves the old scope and branches off into a new one.
console.log("Runs first.");
SomeFunction().then((value) => {console.log("Runs last (probably). Didn't use await on SomeFunction().")})
console.log("Runs second (probably).");
As more explanation to #user280209 answer let's consider the following function which returns promise and compare its execution with .then() and async await.
function call(timeout) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(`This call took ${timeout} seconds`);
resolve(true);
}, timeout * 1000);
});
}
With .then()
(async () => {
call(5).then((r) => {
console.log(r);
});
await call(2); //This will print result first
await call(1);
})();
When running the above call the logs will be
This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true
As we can see .then() didn't pause the execution of its below line until it completes.
With async/wait
(async () => {
await call(5); //This will print result first
await call(2);
await call(1);
})();
When run the above function logs will be
This call took 5 seconds
This call took 2 seconds
This call took 1 seconds
So I think if your promise's result won't be used in the following lines, .then() may be better.
For those saying await blocks the code until the async call returns you are missing the point. "await" is syntactic sugar for a promise.then(). It is effectively wrapping the rest of your function in the then block of a promise it is creating for you. There is no real "blocking" or "waiting".
run();
async function run() {
console.log('running');
makePromises();
console.log('exiting right away!');
}
async function makePromises() {
console.log('make promise 1');
const myPromise = promiseMe(1)
.then(msg => {
console.log(`What i want to run after the promise is resolved ${msg}`)
})
console.log('make promise 2')
const msg = await promiseMe(2);
console.log(`What i want to run after the promise is resolved via await ${msg}`)
}
function promiseMe(num: number): Promise<string> {
return new Promise((resolve, reject) => {
console.log(`promise`)
resolve(`hello promise ${num}`);
})
}
The await line in makePromises does not block anything and the output is:
running
make promise 1
promise
make promise 2
promise
exiting right away!
What i want to run after the promise is resolved hello promise 1
What i want to run after the promise is resolved via await hello promise 2
Actually.
Await/Async can perform more efficiently as Promise.then() loses the scope in which it was called after execution, you are attaching a callback to the callback stack.
What it causes is: The system now has to store a reference to where the .then() was called. In case of error it has to correctly point to where the error happens, otherwise, without the scope (as the system resumed execution after called the Promise, waiting to comeback to the .then() later) it isn't able to point to where the error happened.
Async/Await you suspend the exection of the method where it is being called thus preserving reference.
If we just consider performance(time taken) then it actually depends on whether your operations are serial or parallel. If your tasks are serial then there will be no difference between await and .then. But if your tasks are parallel then .then will take less time. Consider the following example
let time = Date.now();
// first task takes 1.5 secs
async function firstTask () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
},1500)
})
}
// second task takes 2 secs
async function secondTask () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2);
},2000)
})
}
// using await
async function call(){
const d1 = await firstTask();
const d2 = await secondTask();
console.log(Date.now()-time, d1+d2)
}
call()
// using .then
async function call2(){
let d1=null,d2=null;
firstTask().then(data => {
d1=data;
if(d2){
console.log(Date.now()-time, d1+d2);
}
})
secondTask().then(data => {
d2=data;
if(d1){
console.log(Date.now()-time, d1+d2);
}
})
}
call2()
Here are the two tasks, first takes 1.5 secs and second takes 2 secs. Call function uses await where as call2 function uses .then . The output is as follows
From call2 2012 3
From call 3506 3
I hope it helps.
As far as I understand .then() and await are not the same thing. An async function won't proceed with the next command until the promise is resolved/rejected since it's basically an implementation of generators. On the contrast, in the case of .then(), the execution of the function will proceed with the next command and the resolve/reject callback will be executed "when there's time" aka when the current event loop (not entirely sure about that part) will be completed.
tldr; on a single promise await and .then() behave similarly but when one promise needs another one to be resolved first then the two of them behave entirely different
Many answer have been provided to this question already. However, to point out key information in the answers above and from my understanding, note below point:
only use await when not handling error return
if no crucial need for error handling use await instead
use .then .catch if returned error message or data is crucial for debugging / or proper error handling instead of try catch for await
Choose any prefer method from code sample below
const getData = (params = {name: 'john', email: 'ex#gmail.com'}) => {
return axios.post(url, params);
}
// anywhere you want to get the return data
// using await
const setData = async () => {
const data = await getData();
}
// to handle error with await
const setData = async () => {
try {
const data = await getData();
}
catch(err) {
console.log(err.message);
}
}
// using .then .catch
const setData = () => {
var data;
getData().then((res) => {
data = res.data; console.log(data)
}).catch((err) => {
console.log(err.message);
});
}
I would like to compose two functions which return Promises into a function which returns a Promise.
I really want to do this for asynchronous system calls, but to simplify things, for now I'm playing with Promises wrapped around setTimeout. Most of the system calls can be sent out and returned in any order, but in a few instances, data from one system call is needed to create a second system call.
In the enclosed example, I want to send out alerts with an interval of 5 seconds, then 3 seconds, then 10 seconds. When I run the code, things run in the wrong order.
I commented out code where I was able to run the two calls chained with ".then". The commented out code works as desired. But I haven't yet figured out how to put that into a function which returns a promise, and still have it work.
I'm interested in doing this using plain JavaScript only. After I understand how to do that, I'll look at answers which do the same using a library.
jsfiddle
// Returns a Promise.
// I purposely chose not to use the callback function inside setTimeout in order to demonstrate
// how to combine functions which return Promises, and normal functions which don't.
function sleep(delay, callbackFunction) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, callbackFunction), delay)
});
}
// Normal function, does not return a promise.
const myPrint = (message, value) => {
alert(message + " " + value);
};
// A function combining a promise and then a normal function.
// Returns a Promise.
const sleepPrint = (delay) => {
return sleep(delay)
.then(() => {
myPrint("sleepPrint()", delay);
});
};
// A function combining two functions which return promises.
// Returns a Promise.
const sleepPrintSleepPrint = (delay1, delay2) => {
return sleepPrint(delay1)
.then(sleepPrint(delay2));
};
alert("Begin");
/*
// Run a Pomise function, then a normal function.
const delay = 4000;
sleep(delay)
.then(() => {
myPrint("init", delay);
});
*/
const firstDelay = 5000;
const secondDelay = 3000;
/*
// Call sleepPrint() which runs a Promise function then a normal function.
// After all that finishes, call another Promise function, than another normal function.
// This code works as desired, but the code at the bottom doesn't!
sleepPrint(firstDelay)
.then(() => {
return sleep(secondDelay)
})
.then(() => {
myPrint("After sleepPrint() and sleep()", secondDelay);
});
*/
// Comine two calls to sleepPrint() into a new functiion which returns a Promise, sleepPrintsleepPrint().
// After all that finishes, call another Promise function, than another normal function.
// I want this to have 5 second delay and then a 3 second delay, but they are not running in that order.
const thirdDelay = 10000;
sleepPrintSleepPrint(firstDelay, secondDelay)
.then(() => {
return sleep(thirdDelay)
})
.then(() => {
myPrint("After sleepPrintSleepPrint()", thirdDelay);
});
Remember how functions work (in any programming language). This:
const sleepPrintSleepPrint = (delay1, delay2) => {
return sleepPrint(delay1)
.then(sleepPrint(delay2));
};
Is the same as this:
const sleepPrintSleepPrint = (delay1, delay2) => {
var x = sleepPrint(delay2);
return sleepPrint(delay1)
.then(x);
};
What you are doing is calling both functions simultaneously. What I think you intend is to call the second function once then resolves. So you need to do this:
const sleepPrintSleepPrint = (delay1, delay2) => {
return sleepPrint(delay1)
.then(function(){return sleepPrint(delay2)});
};
Or if you prefer arrow function syntax:
const sleepPrintSleepPrint = (delay1, delay2) => {
return sleepPrint(delay1)
.then(() => sleepPrint(delay2));
};
#slebetman supplied the correct code, and he explained the issue and the fix correctly at a high level. This is my understanding of his answer in more detail. This should be a comment to his answer, but it's too big.
The JavaScript interpreter makes two passes through code which contains chained ".then"s.
The first pass happens right away without any waiting. The interpreter looks at the argument(s) to .then, and does something different if it sees a function or an expression. Functions are placed onto the call stack, and associated with a promise. Expressions are evaluated, and if the completion value is a function, the function is placed onto the call stack, and associated with a promise.
In the second pass, after a promise has been resolved, the associated function from the call stack is evaluated.
In production code, chained .then's should always follow a specific pattern. The pattern is that the argument to ".then" is one function which returns a second callback function. In the first pass, nothing very interesting happens, the first function is executed, and the return value is the second callback function. The second callback function is placed onto the call stack and associated with a promise. In the second pass, after the associated promise has been resolved, the second callback function is executed.
But in this example, I am breaking the pattern in order to learn and demonstrate how chained .then's work.
Below is an example which does not use the pattern, and exposes the two pass behavior.
This is talking about the two arguments to .then, the success callback function, and the failure callback function.
"If one or both arguments are omitted or are provided non-functions, then then will be missing the handler(s), but will not generate any errors."
If you give a function to ".then", then in the first pass, the function is placed on the call stack, but nothing else happens, and in the second pass, the function is executed.
But if you give an expression to ".then", then in the first pass, the expression is evaluated. If the completion value is a function, it is placed onto the call stack, and executed in the second pass. If the completion value is not a function, in the second pass, no further action is taken, and no error is generated.
First Pass (The JavaScript interpreter runs these things immediateley.)
Kick off sleepPrint(firstDelay). Let it run in the background.
Immediately go to the next ".then".
Print the first message. Put nothing on the call stack.
Immediately go to the next ".then".
Put the function () => sleepPrint(secondDelay) onto the call stack, and associate it with the preceding promise.
Immediately go to the next ".then".
Print the second message. Put nothing on the call stack.
Second Pass (The JavaScript interpreter runs each of these steps from the call stack much later, after the corresponding promise has been resolved.)
Wait until sleepPrint(firstDelay) prints the third message, and is resolved, then go to the next item on the call stack.
There's nothing on the call stack for this slot. There's no promise to resolve, so go to the next item on the call stack. No error is generated.
Execute function () => sleepPrint(secondDelay) which prints the fourth message. Wait for the promise to be resolved, then go to the next item on the call stack.
There's nothing on the call stack for this slot. There's no promise to resolve. No error is generated.
jsFiddle
// Returns a Promise.
// I purposely chose not to use the callback function inside setTimeout in order to demonstrate
// how to combine functions which return Promises, and normal functions which don't.
function sleep(delay, callbackFunction) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, callbackFunction), delay)
});
}
// Normal function, does not return a promise.
const myPrint = (message, value) => {
alert(message + " " + value);
};
// A function combining a promise and then a normal function.
// Returns a Promise.
const sleepPrint = (delay) => {
return sleep(delay)
.then(() => {
myPrint("sleepPrint()", delay);
});
};
alert("Begin");
const firstDelay = 5000;
const secondDelay = 3000;
// This message is printed third.
sleepPrint(firstDelay)
.then(
myPrint("This message is printed first", 0)
)
.then(
// This message is printed fourth.
() => {sleepPrint(secondDelay)}
)
.then(
myPrint("This message is printed second", 0)
);