How to use async await function object in Javascript? - javascript

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.

Related

How to call an async function inside an if statement?

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);
}

typescript await in getter [duplicate]

Is it or will it be possible to have an ES6 class getter
return a value from an ES2017 await / async function.
class Foo {
async get bar() {
var result = await someAsyncOperation();
return result;
}
}
function someAsyncOperation() {
return new Promise(function(resolve) {
setTimeout(function() {
resolve('baz');
}, 1000);
});
}
var foo = new Foo();
foo.bar.should.equal('baz');
Update: As others have pointed out, this doesn't really work. #kuboon has a nice workaround in an answer below here..
You can do this
class Foo {
get bar() {
return (async () => {
return await someAsyncOperation();
})();
}
}
which again is the same as
class Foo {
get bar() {
return new Promise((resolve, reject) => {
someAsyncOperation().then(result => {
resolve(result);
});
})
}
}
You can get the value by await on the caller side.
class Foo {
get bar() {
return someAsyncOperation();
}
}
async function test(){
let foo = new Foo, val = await foo.bar;
val.should.equal('baz');
}
You can only await promises, and async functions will return promises themselves.
Of course a getter can yield such a promise just as well, there's no difference from a normal value.
For the value returned by the getter, this changes nothing, since an async function returns a Promise anyway. Where this matters, is in the function, since await can only be used in an async function.
If the issue it that await is wished in the function, I would do:
get property () {
const self = this; // No closure with `this`, create a closure with `self`.
async function f () { // `async` wrapper with a reference to `self`
const x = await self.someFunction(); // Can use `await`
// the rest with “self” in place of “this”
return result;
}
return f(); // Returns a `Promise` as should do an `async get`
}

Does the asyc\await syntax resolve chained functions?

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));

Promise plus number returns promise

I have a simple code
async function foo() {
const b = bar()
return 2 + b
}
async function bar() {
return 2
}
(async() => {
console.log(typeof foo())
})()
and it logs object. Not NaN. How does it happen that number + object -> object?
From what I remember from + spec if one of the operands is a primitive and second is an object then object should be converted to primitive. In this case with .valueOf() method
It think it's because async functions are not resolved yet in your case, becaue there is no await. So you are getting promise objects instead of your result.
see these cases:
async function foo () {
const b = await bar() //await result
return 2 + b
}
async function bar () {
return 2
}
;(async () => {
console.log(typeof await foo()) //number
})()
async function foo () {
const b = bar() //no await
return 2 + b
}
async function bar () {
return 2
}
;(async () => {
console.log(typeof await foo()) //string
})()
The functions foo and bar return a promise, so, you're getting the type of promise (Object)
Probably you want to compare the result, so you need to wait for promise resolves the concatenation:
let result = await foo();
^
async function foo() {
const b = bar() // Here you need to wait as well.
return 2 + b; // 2 + "[object Promise]"
}
async function bar() {
return 2
}
(async() => {
let result = await foo();
console.log(result);
console.log(typeof result);
})()
Now, to get the NaN value you need to convert to number:
async function foo() {
const b = bar(); // Here you need to wait as well.
return Number(2 + b); // <- Try to conver to number
}
async function bar() {
return 2
}
(async() => {
let result = await foo();
console.log(result);
console.log(typeof result);
})()

Async / await assignment to object keys: is it concurrent?

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}))

Categories