Change the value of variable with the resolve data of promise - javascript

How to change the value of data inside the asyncCall() and set it to the resolve value of the promise which is b.
What I wanted is that the asyncCall() will return b.
But what happen is that asyncCall() returns a Promise object.
function resolveAfter2Seconds(data) {
return new Promise(resolve => {
resolve(data);
});
}
async function asyncCall() {
let data = "a";
var result = await resolveAfter2Seconds("b");
data = result;
return data;
}
asyncCall();

Use IIFE
Making the function async will automatically have it return a Promise. You will either have to await it, or use .then to access the resolved value. IIFE stands for "Immediately Invoked Function Expression" – Tim VN
function resolveAfter2Seconds(data) {
return new Promise(resolve => {
resolve(data);
});
}
async function asyncCall() {
let data = "a";
var result = await resolveAfter2Seconds("b");
data = result;
return data;
}
(async function() {
console.log(await asyncCall())
})()

An async function will always return a Promise (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#Return_value).
If you put a console.log(result) statement in the asyncCall() function body, you will realize that the value is actually resolved right there and can be used as you'd expect it. But as documented, the return value of an async function will always be "promisified", so you'd have to "await" that function call too.
To do that at the top (global) level, you can either use an IIFE (Immediately Invoked Function Expression):
(async () => console.log(await asyncCall()))();
or fall back to classical callback functions using Promise.then():
asyncCall().then(value => console.log(value));
Some browsers also support top level await expressions:
await asyncCall();

declaring function with async will return classic Promise.
so you have to use callbacks or await.
async function asyncCall() will return Promise not the result you want to.
asyncCall().then((data) => console.log('in data is your result'));

Async functions return a promise itself:
function resolveAfter2Seconds(data) {
return new Promise(resolve => {
return resolve(data);
});
}
async function asyncCall() {
const result = await resolveAfter2Seconds("b");
return result;
}
asyncCall().then(
data => console.log(data)
);

Related

Node.js I keep getting Promise { <pending> } when I make an API call then try to save results to variable and then log to console [duplicate]

I read that async functions marked by the async keyword implicitly return a promise:
async function getVal(){
return await doSomethingAync();
}
var ret = getVal();
console.log(ret);
but that is not coherent...assuming doSomethingAsync() returns a promise, and the await keyword will return the value from the promise, not the promise itsef, then my getVal function should return that value, not an implicit promise.
So what exactly is the case? Do functions marked by the async keyword implicitly return promises or do we control what they return?
Perhaps if we don't explicitly return something, then they implicitly return a promise...?
To be more clear, there is a difference between the above and
function doSomethingAync(charlie) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(charlie || 'yikes');
}, 100);
})
}
async function getVal(){
var val = await doSomethingAync(); // val is not a promise
console.log(val); // logs 'yikes' or whatever
return val; // but this returns a promise
}
var ret = getVal();
console.log(ret); //logs a promise
In my synopsis the behavior is indeed inconsistent with traditional return statements. It appears that when you explicitly return a non-promise value from an async function, it will force wrap it in a promise.
I don't have a big problem with it, but it does defy normal JS.
The return value will always be a promise. If you don't explicitly return a promise, the value you return will automatically be wrapped in a promise.
async function increment(num) {
return num + 1;
}
// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));
Same thing even if there's no return! (Promise { undefined } is returned)
async function increment(num) {}
Same thing even if there's an await.
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function incrementTwice(num) {
const numPlus1 = await defer(() => num + 1);
return numPlus1 + 1;
}
// Logs: 5
incrementTwice(3).then(num => console.log(num));
Promises auto-unwrap, so if you do return a promise for a value from within an async function, you will receive a promise for the value (not a promise for a promise for the value).
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function increment(num) {
// It doesn't matter whether you put an `await` here.
return defer(() => num + 1);
}
// Logs: 4
increment(3).then(num => console.log(num));
In my synopsis the behavior is indeed inconsistent with traditional
return statements. It appears that when you explicitly return a
non-promise value from an async function, it will force wrap it in a
promise. I don't have a big problem with it, but it does defy normal
JS.
ES6 has functions which don't return exactly the same value as the return. These functions are called generators.
function* foo() {
return 'test';
}
// Logs an object.
console.log(foo());
// Logs 'test'.
console.log(foo().next().value);
Yes, an async function will always return a promise.
According to the tc39 spec, an async function desugars to a generator which yields Promises.
Specifically:
async function <name>?<argumentlist><body>
Desugars to:
function <name>?<argumentlist>{ return spawn(function*() <body>, this); }
Where spawn "is a call to the following algorithm":
function spawn(genF, self) {
return new Promise(function(resolve, reject) {
var gen = genF.call(self);
function step(nextF) {
var next;
try {
next = nextF();
} catch(e) {
// finished with failure, reject the promise
reject(e);
return;
}
if(next.done) {
// finished with success, resolve the promise
resolve(next.value);
return;
}
// not finished, chain off the yielded promise and `step` again
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
Your question is: If I create an async function should it return a promise or not? Answer: just do whatever you want and Javascript will fix it for you.
Suppose doSomethingAsync is a function that returns a promise. Then
async function getVal(){
return await doSomethingAsync();
}
is exactly the same as
async function getVal(){
return doSomethingAsync();
}
You probably are thinking "WTF, how can these be the same?" and you are right. The async will magically wrap a value with a Promise if necessary.
Even stranger, the doSomethingAsync can be written to sometimes return a promise and sometimes NOT return a promise. Still both functions are exactly the same, because the await is also magic. It will unwrap a Promise if necessary but it will have no effect on things that are not Promises.
Just add await before your function when you call it :
var ret = await getVal();
console.log(ret);
async doesn't return the promise, the await keyword awaits the resolution of the promise. async is an enhanced generator function and await works a bit like yield
I think the syntax (I am not 100% sure) is
async function* getVal() {...}
ES2016 generator functions work a bit like this. I have made a database handler based in top of tedious which you program like this
db.exec(function*(connection) {
if (params.passwd1 === '') {
let sql = 'UPDATE People SET UserName = #username WHERE ClinicianID = #clinicianid';
let request = connection.request(sql);
request.addParameter('username',db.TYPES.VarChar,params.username);
request.addParameter('clinicianid',db.TYPES.Int,uid);
yield connection.execSql();
} else {
if (!/^\S{4,}$/.test(params.passwd1)) {
response.end(JSON.stringify(
{status: false, passwd1: false,passwd2: true}
));
return;
}
let request = connection.request('SetPassword');
request.addParameter('userID',db.TYPES.Int,uid);
request.addParameter('username',db.TYPES.NVarChar,params.username);
request.addParameter('password',db.TYPES.VarChar,params.passwd1);
yield connection.callProcedure();
}
response.end(JSON.stringify({status: true}));
}).catch(err => {
logger('database',err.message);
response.end(JSON.stringify({status: false,passwd1: false,passwd2: false}));
});
Notice how I just program it like normal synchronous particularly at
yield connection.execSql and at yield connection.callProcedure
The db.exec function is a fairly typical Promise based generator
exec(generator) {
var self = this;
var it;
return new Promise((accept,reject) => {
var myConnection;
var onResult = lastPromiseResult => {
var obj = it.next(lastPromiseResult);
if (!obj.done) {
obj.value.then(onResult,reject);
} else {
if (myConnection) {
myConnection.release();
}
accept(obj.value);
}
};
self._connection().then(connection => {
myConnection = connection;
it = generator(connection); //This passes it into the generator
onResult(); //starts the generator
}).catch(error => {
reject(error);
});
});
}

Does async tag wrap a JavaScript function with a Promise?

So I understand that "async" ensures that a function will return a Promise, and if it doesn't then it wraps it in a promise.
My question is, if the function is already returning a Promise, does "async" wrap it in another Promise?
async function, return non-Promise:
async function foo() {
return 5;
}
console.log(foo()) // Promise { 5 }
regular function, return Promise:
function foo() {
return Promise.resolve(5);
}
console.log(foo()) // Promise { 5 }
async function, return Promise:
async function foo() {
return Promise.resolve(5);
}
console.log(foo()) // Promise { <pending> }
Why does the last one return "Promise { pending }" ? My intuition tells me the redundant "async" tag is wrapping the already returned Promise with another Promise. Is this correct?
If an async function returns a Promise, then the Promise returned by that function will resolve to the same value as the original Promise. This can be seen with a simple example:
async function foo() {
return Promise.resolve(42);
}
console.log(await foo()); // "42", not "Promise { 42 }"
So in most normal situations, we can simply imagine that the Promise returned by the code inside the async function body is returned without being touched. But as you've stumbled across, even though the Promise returned by an async function will resolve to the same value as a Promise returned by the code, the actual Promise object is not necessarily the same:
let p1;
async function foo() {
p1 = Promise.resolve(42);
return p1;
}
let p2 = foo();
console.log('p1 === p2 ?', p1 === p2); // "false" (!)
So we can see that the Promise object returned by the function invocation is actually different from the Promise object that the function body returned. No matter, though, it will give the same result when we await it (or use Promise.then()):
let p1;
async function foo() {
p1 = Promise.resolve(42);
return p1;
}
let p2 = foo();
console.log(await p1); // '42'
console.log(await p2); // also '42'
(Note that to run these examples in e.g. a node repl shell, you'll need to wrap them like:
async function main() {
/* code using async / await here */
}
main();
You need to call your last function as:
foo.then(function(r){console.log(r)});
The reason being, an async function needs to return a promise. A promise will log pending until the result is resolved. To capture the promise, you must call "then".
Here is a link for more info about then:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
Here is a link for more info about async functinos:
https://fmpapidev.holstein.ca/swagger/index.html
Now I'm not certain what the native implementation of async/ await is for modern node apps but if you take a look at what Babel generates when it transpiles to node 6
Take this simple async function:
async function fooAsync() {
return 1;
}
Babel transforms this code to look like this:
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function fooAsync() {
return _fooAsync.apply(this, arguments);
}
function _fooAsync() {
_fooAsync = _asyncToGenerator(function* () {
return 1;
});
return _fooAsync.apply(this, arguments);
}
You can see the transformation of your async method and the state machine it generates. The interesting part is that the generator, when executed, return a new Promise(). So to answer your question, just having the keyword async in your function, would make it return a Promise. This can also be seen in Typescript where the compiler will moan if you have an async method and you don't specify a return type of Promise<T>

Why async returns promise in JS [duplicate]

I read that async functions marked by the async keyword implicitly return a promise:
async function getVal(){
return await doSomethingAync();
}
var ret = getVal();
console.log(ret);
but that is not coherent...assuming doSomethingAsync() returns a promise, and the await keyword will return the value from the promise, not the promise itsef, then my getVal function should return that value, not an implicit promise.
So what exactly is the case? Do functions marked by the async keyword implicitly return promises or do we control what they return?
Perhaps if we don't explicitly return something, then they implicitly return a promise...?
To be more clear, there is a difference between the above and
function doSomethingAync(charlie) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(charlie || 'yikes');
}, 100);
})
}
async function getVal(){
var val = await doSomethingAync(); // val is not a promise
console.log(val); // logs 'yikes' or whatever
return val; // but this returns a promise
}
var ret = getVal();
console.log(ret); //logs a promise
In my synopsis the behavior is indeed inconsistent with traditional return statements. It appears that when you explicitly return a non-promise value from an async function, it will force wrap it in a promise.
I don't have a big problem with it, but it does defy normal JS.
The return value will always be a promise. If you don't explicitly return a promise, the value you return will automatically be wrapped in a promise.
async function increment(num) {
return num + 1;
}
// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));
Same thing even if there's no return! (Promise { undefined } is returned)
async function increment(num) {}
Same thing even if there's an await.
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function incrementTwice(num) {
const numPlus1 = await defer(() => num + 1);
return numPlus1 + 1;
}
// Logs: 5
incrementTwice(3).then(num => console.log(num));
Promises auto-unwrap, so if you do return a promise for a value from within an async function, you will receive a promise for the value (not a promise for a promise for the value).
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function increment(num) {
// It doesn't matter whether you put an `await` here.
return defer(() => num + 1);
}
// Logs: 4
increment(3).then(num => console.log(num));
In my synopsis the behavior is indeed inconsistent with traditional
return statements. It appears that when you explicitly return a
non-promise value from an async function, it will force wrap it in a
promise. I don't have a big problem with it, but it does defy normal
JS.
ES6 has functions which don't return exactly the same value as the return. These functions are called generators.
function* foo() {
return 'test';
}
// Logs an object.
console.log(foo());
// Logs 'test'.
console.log(foo().next().value);
Yes, an async function will always return a promise.
According to the tc39 spec, an async function desugars to a generator which yields Promises.
Specifically:
async function <name>?<argumentlist><body>
Desugars to:
function <name>?<argumentlist>{ return spawn(function*() <body>, this); }
Where spawn "is a call to the following algorithm":
function spawn(genF, self) {
return new Promise(function(resolve, reject) {
var gen = genF.call(self);
function step(nextF) {
var next;
try {
next = nextF();
} catch(e) {
// finished with failure, reject the promise
reject(e);
return;
}
if(next.done) {
// finished with success, resolve the promise
resolve(next.value);
return;
}
// not finished, chain off the yielded promise and `step` again
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
Your question is: If I create an async function should it return a promise or not? Answer: just do whatever you want and Javascript will fix it for you.
Suppose doSomethingAsync is a function that returns a promise. Then
async function getVal(){
return await doSomethingAsync();
}
is exactly the same as
async function getVal(){
return doSomethingAsync();
}
You probably are thinking "WTF, how can these be the same?" and you are right. The async will magically wrap a value with a Promise if necessary.
Even stranger, the doSomethingAsync can be written to sometimes return a promise and sometimes NOT return a promise. Still both functions are exactly the same, because the await is also magic. It will unwrap a Promise if necessary but it will have no effect on things that are not Promises.
Just add await before your function when you call it :
var ret = await getVal();
console.log(ret);
async doesn't return the promise, the await keyword awaits the resolution of the promise. async is an enhanced generator function and await works a bit like yield
I think the syntax (I am not 100% sure) is
async function* getVal() {...}
ES2016 generator functions work a bit like this. I have made a database handler based in top of tedious which you program like this
db.exec(function*(connection) {
if (params.passwd1 === '') {
let sql = 'UPDATE People SET UserName = #username WHERE ClinicianID = #clinicianid';
let request = connection.request(sql);
request.addParameter('username',db.TYPES.VarChar,params.username);
request.addParameter('clinicianid',db.TYPES.Int,uid);
yield connection.execSql();
} else {
if (!/^\S{4,}$/.test(params.passwd1)) {
response.end(JSON.stringify(
{status: false, passwd1: false,passwd2: true}
));
return;
}
let request = connection.request('SetPassword');
request.addParameter('userID',db.TYPES.Int,uid);
request.addParameter('username',db.TYPES.NVarChar,params.username);
request.addParameter('password',db.TYPES.VarChar,params.passwd1);
yield connection.callProcedure();
}
response.end(JSON.stringify({status: true}));
}).catch(err => {
logger('database',err.message);
response.end(JSON.stringify({status: false,passwd1: false,passwd2: false}));
});
Notice how I just program it like normal synchronous particularly at
yield connection.execSql and at yield connection.callProcedure
The db.exec function is a fairly typical Promise based generator
exec(generator) {
var self = this;
var it;
return new Promise((accept,reject) => {
var myConnection;
var onResult = lastPromiseResult => {
var obj = it.next(lastPromiseResult);
if (!obj.done) {
obj.value.then(onResult,reject);
} else {
if (myConnection) {
myConnection.release();
}
accept(obj.value);
}
};
self._connection().then(connection => {
myConnection = connection;
it = generator(connection); //This passes it into the generator
onResult(); //starts the generator
}).catch(error => {
reject(error);
});
});
}

Javascript, two async/await and promise func but one is working and the other is not working

my utils.js have two funcs. i using in the electron#2.0.2.
async function detectMimeType(filePath) {
let detectMime=new Promise((resolve, reject) => {
// mmmagic npm module
magic.detectFile(filePath, function(err, result) {
if (err) reject(err);
resolve(result);
});
});
let result = await detectMime;
return result;
}
async function parseXML(data) {
let parse = new Promise((resolve, reject) => {
// xml2js npm module
parser.parseString(data,function(err,xmldata){
if (err) reject(err);
resolve(xmldata);
});
});
let result = await parse;
return result;
}
detectMimeType func returning result. but parseXML func returning Promise object pending.
let mime = detectMimeType('testingSound.mp3'); // returning 'audio/mpeg';
let xmlPayload =
parseXML('<root><test>testData</test></root>'); //returning Promise object pending
but it works like this.
async function init(){
let xmlPayload =
await parseXML('<root><test>testData</test></root>');
}
Why does not it work like detectMimeType?
UPDATE: detectMimeType and parseXML two func returning Promise Object.
async functions always return a Promise.
Functions declared as async function always return promises, even if their body is completely synchronous:
async function foo() {
// seemingly synchronous code
return "bar!";
}
const a = foo(); // Promise<pending>
const b = await foo(); // "bar!"
Whatever you return from the async function, is passed to the either resolve() or reject() function of the implicit promise that has been created as the result of async function invocation.
So, you have always await foo() for the result, or use foo().then() if you are forced to use callbacks.
In general case, return await promise is merely a self-documentating construct, effectively equivalent to return promise, because promise would be in any case awaited as part of the implicit return promise resolve process.
Also, given your intent, I'd suggest promisifying your functions using standard Node.js util.promisify or Bluebird.promisify (whichever is available to you):
const { promisify } = require('util');
const detectMimeType = promisify(magic.detectFile);
const parseXML = promisify(parser.parseString);
This keeps them functionally equivalent to the code you have produced already, but restraints from excessive use of new Promise(), generally frowned upon.

Is async needed when returning a promise? [duplicate]

This question already has answers here:
What is the benefit of prepending async to a function that returns a promise?
(2 answers)
Closed 4 years ago.
I understand that we use async when we want to use await inside a function, but if the function returns a promise (without awaiting it), should we prefix the name with async?
Example 1:
async function fetching() {
return fetch('someUrl')
}
Example 2:
function fetching() {
return fetch('someUrl');
}
What is more proper, example 1 or example 2?
async and await are just convenience methods to work with promises.
async function foo(){
return true;
}
is exactly the same as
function bar(){
return new Promise(resolve => {
resolve(true);
});
}
because async encapsulates the return value in a promise, which is resolved, when the method finishes.
In a similiar way
async function oof(){
let myVal = await foo();
do_something_else();
}
(Note: async only has to be used here to be able to use await)
is the same as
function rab(){
let myVal;
bar().then(val => myVal = val);
}
await just makes it easier to chain promises
The result of an async function is automatically wrapped in Promise.resolve, this means that if you return a Promise, it will be unwrapped automatically. In essence, it does not matter.
const delay = x => new Promise(res => setTimeout(() => {
console.log("Resolved");
res();
}, x));
function fetch()
{
return delay(1000);
}
async function fetchA()
{
return delay(1000);
}
(async () =>
{
console.log("Create fetch");
const f1 = fetch();
console.log("Await fetch");
await f1;
console.log("Awaited fetch");
console.log("Create fetchA");
const f2 = fetchA();
console.log("Await fetchA");
await f2;
console.log("Awaited fetchA");
})();

Categories

Resources