I'm struggling a bit with async/await and returning a value from a Promise.
function test () {
return new Promise((resolve, reject) => {
resolve('Hello')
})
}
async function c() {
await test()
}
As I understood things I should be able to get a value by doing:
console.log(c())
But clearly I am missing a point here as this returns a promise. Shouldn't it print "hello"? On a similar note I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
I am missing a point here as this returns a promise. Shouldn't console.log(c()) print "hello"?
No, async functions always return promises. They're not magically running asynchronous code synchronously - rather the reverse, they turn synchronous-looking code (albeit speckled with await keywords) into asynchronously running one.
You can get the result value inside the asynchronous function:
async function c() {
const result = await test()
console.log(result);
return 'World';
}
c().then(console.log);
I am unclear as to whether a callback needs to be converted to a promise before wrapping it in async/await?
Yes, you can await only promises. See How do I convert an existing callback API to promises? for how to do the conversion.
Async functions return a Promise. If the function throws an error, the
Promise will be rejected. If the function returns a value, the Promise
will be resolved.
Related
How is an asynchronous function such as fs.readFile written such that it is asynchronous but different from a function decorated with the async keyword? Does an async function always return a promise?
The following works:
const Area = async (L, B) => L * B;
Area(5, 4).then(
a => console.log("Area is " + a)
);
However, a function like fs.readFile after invocation will result in an undefined value.
When using a function from a third-party library, is there a way to tell that a function is asynchronous other than from its documentation?
fs.readFile implements asynchronousness through a callback, it returns nothing.
By contrast, fsPromises.readFile implements asynchronousness by returning a promise.
The callback flavor of asynchronousness can be converted into the promise flavor with the util.promisify function.
The async prefix must be applied to a function if the code in the function body makes use of the await keyword. A function with that prefix always returns a promise (like your Area), but promise-returning functions are possible without the async prefix, for example:
function timeout(ms) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, ms);
});
}
Whether a function is asynchronous, and if so whether it uses the callback or promise flavor should be documented. If that is not the case, you can only try out its behavior. Note that a function could have several callbacks, and perhaps also return a promise. There are more types of asynchronous behavior than just the one enabled by async.
let request = require('request-promise')
function get(url) {
let _opt = {}
let response = (async () => {
try {
var ret = await request(url, _opt);
return ret;
} catch (e) {
console.log(e)
}
})();
return response
}
console.log(get('http://www.httpbin.org/ip'))
gives:
Promise { <pending> }
Why doesn't it wait for my response?
Why doesn't it wait for my response?
That's simple, because you are returning a promise. Node js is single thread and is executed in a non blocking way.
That means that return response in your get function is executed before the resolution of response variable.
Try as follow:
let request = require('request-promise')
function get(url) {
let _opt = {}
return request(url, _opt);
}
async function some () {
console.log(await get('http://www.httpbin.org/ip'));
}
some();
This example is also returning a promise, but in this case we are awaiting for the promise resolution.
Hope this help.
Async functions are non-blocking and will immediately return a promise rather than waiting for a result. This for example, allows for multiple async functions to run concurrently rather than each running sequentially.
To wait for a result, you can use the await keyword to block until the promise is resolved. The await command will return the result of the promise. For example, to log the result of the get function, you can change the last line to:
console.log(await get('http://www.httpbin.org/ip'))
UPDATE:
Let me give this one more try (sorry if I'm beating a dead horse here).
Since your response variable is an async function, it's return type is a promise by the definition of an async function. Even though the ret variable is await'ed, that just means that it will block while writing to the ret variable. The response async function needs to be run to completion in order for the await to complete. An await here would be useful if you wanted to wait for the return value and then add post-processing, but in this example specifically, your try block could simply be:
try {
return request(url, _opt)
}
Since request already returns a promise, the extra await is causing a trivial amount of overhead since it implicitly creates an extra promise.
Since response is a promise, and you are returning response, the function get is also returning a promise. You are then trying to log this promise (which obviously doesn't work). This is why you must await or .then the get function to get the result.
Source: https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8 under "Pitfall 1: not awaiting"
I have a chain of 4 promises, and 1 function at the end. The final function is executing before the previous promises in the chain have resolved.
Can someone explain to me why this might be happening?
Here is the promise chain:
updateGdax(db)
.then(updateBitstamp(db))
.then(updateBitfinex(db))
.then(updatePoloniex(db))
.then(coinMarketData.updateCoinMarketData(db))
.then(addRates(db)); //this function is executing after the first promise in the chain.
I would like each function to execute after the one listed before it, so addRates(db) should be executed last.
I can post the code from the promise functions if needed for further analyses, but I really just want to understand WHY this would happen, as my understanding is that functions in a promise chain won't execute unless the previous promise in the chain has resolved.
Unless those update functions in the then calls are partially applied (unless they return a function), they are being executed before the then is called. You need to wrap them in an anonymous function to have them executed in order. Do what the other answer says or use fat arrows:
updateGdax(db)
.then(()=>updateBitstamp(db))
.then(()=>updateBitfinex(db))
.then(()=>updatePoloniex(db))
.then(()=>coinMarketData.updateCoinMarketData(db))
.then(()=>addRates(db));
If your update functions could be rewritten to return the db after completing, then you could rewrite the calls like so, point free style:
updateGdax(db)
.then(updateBitstamp)
.then(updateBitfinex)
.then(updatePoloniex)
.then(coinMarketData.updateCoinMarketData)
.then(addRates);
Each function, would then look something like this:
function updateGdax(db) {
return db.doSomething().then(()=> db)
}
Follow that pattern, and you have yourself some nice looking javascript.
And have a look at the new async/await, included in nodejs 8. It is much more intuitive:
async function main() {
await updateGdax(db)
await updateBitstamp(db)
await updateBitfinex(db)
await updatePoloniex(db)
await coinMarketData.updateCoinMarketData(db)
await addRates(db)
}
main().catch(e => console.error(e))
Try below approach,
updateGdax(db)
.then(function(){
return updateBitstamp(db)
}).then(function (){
return updateBitfinex(db);
}).then(function() {
return updatePoloniex(db);
}).then(function(){
return coinMarketData.updateCoinMarketData(db)
}).then(function(){
return addRates(db);
}).catch(function(err){
console.log(err);
});
Hope this will work. If any of the function is returning any value and if you want to use it in subsequent function the pass that value in following function() used inside then. Refer : https://strongloop.com/strongblog/promises-in-node-js-an-alternative-to-callbacks/
I need help with debugging this code/or learn efficient way to do it- I tried using bluebird.each to capture all executions within my forEach, but didn't get it work. Same with setting up a new promise with pure javascript. I need help how to execute my forEach FIRST and move on.
let arr = [];
let fields = ['environment', 'habitat', 'earth]
Promise.each(fields, field => {
nano.db.use(field).view('options', 'options')
.spread((body, header) => {
arr.push(body.rows);
})
}).then(() => console.log(arr))
Expected outcome:
arr to console.log ====> [1,2,3,4,5]
Actual outcome:
arr is an empty array ====> [ ]
I see it's a problem with asynchronicity, but I can't seem to figure out how to actually make this work. any input or resources will be greatly appreciated!
I haven't actually ran your code so sorry if I'm incorrect, but from looking at it and the bluebird docs I assume the correction you need to make is return your nano.db call wrapped in a promise inside the Promise.each
let arr = [];
let fields = ['environment', 'habitat', 'earth']
Promise.each(fields, field => {
return new Promise ((resolve, reject) => {
nano.db.use(field).view('options', 'options')
.spread((body, header) => {
arr.push(body.rows);
resolve();
})
});
}).then(() => console.log(arr))
I believe your assumption is right that you're having a problem with asynchronicity when getting an empty array back instead of what you expect. I'm assuming the .then method is firing before the nano.db gets back with the data.
I wrapped your call of nano.db in a promise so that it will await nano.db finishing since Promise.each supports returning promises inside it.
Bluebird's promise docs state with Promise.each.
If the iterator function returns a promise or a thenable, then the
result of the promise is awaited before continuing with next
iteration.
So, if a promise is not returned in your Promise.each and anything that is asynchronous happens inside then just as with a then or a catch method on a promise under the same circumstances.
As I do not know bluebird there may be a way to change that promise to be more bluebird like. The promise I wrapped around the nano.db call is just a normal es6 promise which bluebird may or may not have a different api for creating promises.
I have written code using Q.reduce mechanism where function insertItemIntoDatabase(item) returns resolved promises.
items.reduce(function(soFar,item)
{
return soFar.then(function()
{
return insertItemIntoDatabase(item);
});
},Q());
Is there any possibilty to wait till chain is finished and then execute another function or I should chain those functions in some other way.
Thanks for help in advance
.reduce() will return the final value from the .reduce() loop, which in your case is a final promise. To execute something after the .reduce() chain and all its async operations are done, you just put a .then() handler on that final promise that is returned:
items.reduce(function(soFar,item) {
return soFar.then(function() {
return insertItemIntoDatabase(item);
});
},Q()).then(someOtherFunction);
The purpose of this pattern is exactly that: to return a promise for the result of the sequence. Written out (without reduce), it's exactly equivalent to the expression
Q()
.then(function() { return insertItemIntoDatabase(items[0]); })
.then(function() { return insertItemIntoDatabase(items[1]); })
.then(function() { return insertItemIntoDatabase(items[2]); })
…
You can simple add another .then() on it that will call your callbacks at the end of the chain.