In this example, if the function was run, would both promises get resolved before foo is return ?
async function() {
var foo = await iReturnAPromise().iReturnAPromiseUnrelatedToMyParent();
return foo;
}
foo as it is, can only carry one resolution. You may do like
foo = await iReturnAPromise().then(v => (doSomeThingWith(v), iReturnAPromiseUnrelatedToMyParent()));
in which case foo will be assigned the resolution of iReturnAPromiseUnrelatedToMyParent. However if you would like to access both resolutions (which are independent of each other) then you may do like;
async function test(){
[foo,bar] = await Promise.all([Promise.resolve(10), Promise.resolve(20)]);
return [foo,bar];
}
test().then(([a,b]) => console.log(a,b));
Related
To keep variables in background.js in chrome extension I need to reinitiate some global variables, and I meet some difficulties.
Here is the code(fiddle) that I want to use to illustrate the problem:
var temp = null;
function someTimeConsumingThing() {
return new Promise(function(resolve,reject) {
setTimeout(resolve, 2000);
temp = 10;
})
}
async function a(){
if(temp==null){
await someTimeConsumingThing();
}
return temp
}
function b(){
let localTemp = a();
console.log(localTemp);
}
b();
In the above code snippet, the temp variable would sometimes be null and to ensure that temp is not null I should call an async function someTimeConsumingThing. As we can see, the console.log outputs a Promise rather than 10; and an error would occur if I add await before a():
Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules"
How can I tackle this problem? I have read many related but unhelpful answers here and I don't know how to optimize my search input to get the most related question. This problem would be very naive for JS experts and there are certainly available answers on this site.
You forgot to use await when calling a(), which means you printed the returned promise instead of the async result of a(). The containing function therefore also needs to be async, since it contains an await call.
Note that it's good practice to mark the someTimeConsumingThing function as async, because it returns a Promise.
Also note that your someTimeConsumingThing function sets temp to 10 immediately, and then delays until returning. I've rewritten it so it only sets temp to 10 after the delay has completed.
let temp = null;
async function someTimeConsumingThing() {
return new Promise(resolve => {
setTimeout(()=>{
temp = 10;
resolve();
}, 2000);
})
}
async function a(){
if(temp==null){
await someTimeConsumingThing();
}
return temp;
}
async function b(){
let localTemp = await a();
console.log(localTemp);
}
b();
A function that calls an async function and needs the result of that function, must in itself (by definition) be asynchronous.
Just change b so that it is an async function:
async function b(){
let localTemp = await a();
console.log(localTemp);
}
can someone explain to me the differenec between the two line of code. In my atom editor the prettier changes the first to second.
(await fetchSearchResults(state.requestConfig, context))?.facilities ?? [] )
and
await fetchSearchResults(state.requestConfig, context)?.facilities ?? [] )
The two lines are not the same and any automated change between these two is most likely incorrect.
To simplify, the difference is between:
(await foo()).bar
await foo() .bar:
Due to the operator precedence of await the second code (await foo().bar) will:
Execute foo()
Read the property bar from it
await that value
Which can be written as:
const functionResult = foo();
const result = await functionResult.bar;
While the first code uses the grouping operator () to change the order of operations to:
Execute foo()
await that value
Read the property bar from it
Which can be written as:
const functionResult = await foo();
const result = functionResult.bar;
This absolutely makes a difference if the function returns a promise:
function foo() {
return Promise.resolve({ bar: "hello world" });
}
async function main() {
console.log( await foo() .bar); // undefined - `foo()` returns a promise and there is no `bar` property
console.log((await foo()).bar); // "hello world" - since the promise resolves to { bar: "hello world" }
}
main();
It also makes a difference if foo() is synchronous but the bar property is a promise:
function foo() {
return { bar: Promise.resolve("hello world") };
}
async function main() {
console.log( await foo() .bar); // "hello world" since the promise resolves to that string
console.log((await foo()).bar); // Promise (check the browser console)
}
main();
The only time it does not make a difference is if there is no asynchronous code (which means the await probably should not be there):
function foo() {
return { bar: "hello world" };
}
async function main() {
console.log( await foo() .bar); // "hello world"
console.log((await foo()).bar); // "hello world"
}
main();
Prettier changes the whole thing to follow the rules given in a Prettier config file.
In your specific case, the (await fetchSearchResults(state.requestConfig, context)) is useless, hence why Prettier strips it.
Meanwhile, it may be quite important in a classic async context as explained in the comment below. Maybe the optional chaining is somehow tricking Prettier here, not sure.
The default Vue2 ESlint configuration comes with plugin:vue/essential and eslint:recommended as defaults.
Here is a link where you could get more details as of why.
If it's Prettier only, check the options part of the documenation or a .prettierrc config file in your project (or above).
You don't need those brackets as long as you are not going to use the promise result straight after as in the example below
(await fetchSearchResults(state.requestConfig, context))?.facilities ?? [] )?.someMethod()
but the line is already getting quite long so you are probably best assigning the promise result to a variable.
I have an ES6 class hierarchy. All of the classes in the hierarchy implement a draw() method. Some implement it synchronously but some need this method to be async.
How can I call draw() correctly in this sort of setup?
Is it possible to find if the method being called is async and only then call await on it's result?
You could check if the draw() has a .then function since all promises will have to implement that. If it does, use async, else execute directly
Check this answer on how to determine a promise How do I tell if an object is a Promise?
if(draw.then) { // all async await functions wrap the return into promises. So, this should
const resolvedData = await draw(); // store the data if you need to get the value
else
draw()
I wanted to avoid having to decla(r)e 100 methods as async for the
sake of just the two that actually need it.
A function doesn't have to be async (ie: return a promise) to be awaited. A synchronous function can be awaited too. This means that if a promise is not returned by draw() (ie: your draw() method is synchronous), then the await will convert the returned value of draw() to a resolved promise which it then waits for and retrieves its value.
So, something like the following is possible:
function foo() { // returns a string
return "foo";
}
async function bar() { // implicitly returns a promise
return "bar";
}
(async function() {
const fooStr = await foo(); // foo() is synchronous, but can be `await`ed still
const barStr = await bar(); // bar() is asynchronous, and can be `await`ed
console.log(fooStr, barStr);
})();
With this in mind, you don't need to know if draw() is synchronous or not, instead, you can always await the draw() method, regardless of its return type.
You can check your function if it is async function by using Object.prototype.constructor.name.
var object = {
draw: async function() {}
}
var object1 = {
draw: function() {}
}
console.log(object.draw.constructor.name);
console.log(object1.draw.constructor.name);
I know that doing this:
const resultA = await a()
const resultB = await b()
// code here
Is effectively
a().then( resultA => {
b().then( resultB => {
// code here
})
})
Basically, a() runs then b() runs. I nested them to show that both resultA and resultB are in our scope; yet both function didn't run at once.
But what about this:
const obj = {
result1: await a(),
result2: await b()
}
do a() and b() run concurrently?
For reference:
const asyncFunc = async (func) => await func.call()
const results = [funcA,funcB].map( asyncFunc )
I know here funcA and funcB do run concurrently.
Bonus:
How would you represent the object assignment
const obj = {
result1: await a(),
result2: await b()
}
using then / callbacks?
UPDATE:
#Bergi is correct in this answer, this occurs sequentially. To share a nice solution for having this work concurrently for an object without having to piece together the object from an array, one can also use Bluebird as follows
const obj2 = Bluebird.props(obj)
http://bluebirdjs.com/docs/api/promise.props.html
No, every await will stop the execution until the promise has fulfilled, even mid-expression. It doesn't matter whether they happen to be part of the same statement or not.
If you want to run them in parallel, and wait only once for their result, you have to use await Promise.all(…). In your case you'd write
const [result1, result2] = await Promise.all([a(), b()]);
const obj = {result1, result2};
How would you represent the object assignment using then / callbacks?
With temporary variables for each awaited value. Every await translates into one then call:
a().then(tmp1 => {
return b().then(tmp2 => {
const obj = {
result1: tmp1,
result2: tmp2
};
return …
});
})
If we wanted to be pedantic, we'd have to pick apart the object creation:
const tmp0 = {};
a().then(tmp1 => {
tmp0.result1 = tmp1;
return b().then(tmp2 => {
tmp0.result2 = tmp2;
const obj = tmp0;
return …
});
})
do a() and b() run concurrently?
No, they run sequentially.
The equivalent would be something like
a()
.then(result1 => b())
.then(result2 => ({result1, result2}))
Say I have a function object-
setObj : function(a,b){
obj.a = a;
obj.b = b;
}
If I have to use async & await on this function object, how do I do it?
If the same was written in function (function way), say-
async function setObj(a,b){
obj.a = a;
obj.b = b;
}
await setObj(2,3);
This works fine. But, how do I do it in case of function object?
If I understand your question correctly, you can just use the async keyword in front of the method declaration:
let obj = {};
let myObj = {
async setObj(a,b) {
obj.a = a;
obj.b = b;
}
}
See http://tc39.github.io/ecmascript-asyncawait/#async-methods
UPDATE
You cannot use await outside of an async function. In order to use this you have to wrap that call to await setObj(2, 3):
async function consoleLog() {
await myObj.setObj(2, 3);
console.log(obj.a + obj.b);
}
consoleLog();
Use the same async keyword in your object's property:
(async function () {
var obj = {};
console.log("hello");
let setObj = async function (a,b){
obj.a = a;
obj.b = b;
};
await setObj(2,3);
console.log(obj.a+obj.b);
})();
Note that the entire code is wrapped in an asynchronous self-invoking function. This is needed, otherwise the await setObj will not be able to run correctly.
using arrow functions work as well
const myObject = {
myFunc: async () => {
await myResultHere
}
}
using this: Since the function is an async function, it will run asynchronously. If you want to run this with await, you will have to use it inside an async function
const useFunc = async () => {
const res = await myObject.myfunc();
}
You can simply put the async keyword on any function, not only function declarations but also function expressions and methods of object. For example:
As an method of an object:
const Object = {
async asyncFunction() {
await MyExamplepromise
}
}
As a variable:
const myFunc = async function () { await MyExamplepromise }
// this is how execute the function expression
// first () operator to execute, and use .then get access the resolved value
myFunc().then((val) => { console.log(val) })
Also notice that an async function returns a promise which will be resolved with the value returned by the async function, or rejected with an uncaught exception thrown from within the async function.