Node.js - prevent async await chaining [duplicate] - javascript

This question already has answers here:
How can I access the value of a promise?
(14 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I am working with node.js and making calls to redis to get some values back. Making this call is async, where I use the await keyword. Like so:
async function getRedisValue(key) {
// does some stuff with the key here...
return await redis.getAsync(key)
}
Note how this uses the async keyword to allow the await. The issue I have is that by doing this, the next time I call this function, I need to use await (or .then()) again because async functions return a promise.
Eventually, this chained calls of await reaches a function in the jsonpath npm package, within the .apply function. Like:
jp.apply(data, path, (key) => {
// I need to return the values from redis here::
return getRedisValue(key);
})
Obviously here, the value returned is a pending promise. If I make that callback async and use the await - I still get a pending promise because the .apply function does not support async .
My question is, can I somehow stop the promise being chained up its hierarchy of calls? some how make getRedisValue not return a promise, but still wait for the redis call to be completed?
Or in general how to handle scenarios like this where I get stuck with nested await's?
Thanks.

Related

How to return a value from a promise which isn't a pending promise: d3.js, Javascript? [duplicate]

This question already has answers here:
async/await implicitly returns promise?
(5 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I am relatively new to asynchronous javascript programming. When using the d3.scv function from the d3 library, I ran into an issue where when awaiting the results of the promise from d3.csv inside a async function scope, I can directly access the resolved value, but when I return this resolved value I get a pending promise.
Code
async function generateCountryData(){
let csvData = await d3.csv("./data/data.csv", (d) => {
return {
"id" : +d["id"], // The '+' turns a string into a number
"country" : d["name"],
"faction" : +d["overlord"]
}
});
let dataArray = csvData.map(Object.values);
// LOG 1
console.log(dataArray);
return dataArray;
}
// LOG 1: Array(58)
// Returns: PromiseĀ {<pending>} "fulfilled"[[PromiseResult]]: Array(58)
async function func1() {
let result = await generateCountryData();
// LOG 2
console.log(result);
return result;
}
// LOG 2: Array(58)
// Returns: PromiseĀ {<pending>} "fulfilled"[[PromiseResult]]: Array(58)
Since I dont want to define a new async function each time I want to access this array, I want to know how I can return a defined resolved value which isn't a pending promise.
It's annoying, but this is how it works. Anything that needs access to the result of an asynchronous operation must itself be asynchronous.
So while there's different patterns for dealing with this (callbacks, observers, promises), you can't get around this so best to embrace it.
You can't turn async code into non-async code. An interesting article about this:
https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/

Handle pending promise while using async await [duplicate]

This question already has answers here:
Async function returning promise, instead of value
(3 answers)
Closed 2 years ago.
I have two time taking functions -> getExcelFileStream and loadWorkbook
I want the function structure to return a response(pass/failure) only after both these subfunctions have been executed.
But it always returns a promise pending clause.
async function parseToJson(data) {
const excelFileStream = await getExcelFileStream(data.url);
const dataRows = await loadWorkbook(excelFileStream, data.orgId);
return dataRows;
}
exports.uploadExcel = function uploadExcel(data) {
return parseToJson(data);
};
According to the doc (Syntax > Return value)
A Promise which will be resolved with the value returned by the async function, or rejected with an exception thrown from, or uncaught within, the async function.
So it should be
exports.uploadExcel = async function uploadExcel(data) {
return await parseToJson(data)
}
It is not possible to make an asynchronous code synchronous in javascript, and with javascript being single threaded, you can't write code to wait for the promise without blokcing the execution of the code handling the promise itself.
I am guessing when you're calling your function uploadExcel, you don't have any await or a .then() so you get a promise instead of the value of the resolved promise.
Unfortunately, You only have two options:
1- Let async/await propagates all the way up in your code
2- Make all your code synchronous, and that would be a very bad idea.

Wait till the subscribe finishes then move on to next part of the code [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
Have a subscription thats being called after everything else gets set but i wanna wait till the subscription finshes. T
Tried using async await but that didnt work with me. No sure if I was doing it incorrectly
public getGlobeConfig() {
this.sourceKey = 'test';query = 'query'
// wait till this call finishes than hit the
console.log('htting')
this.service
.searchQuery(query)
.subscribe(response => {
this.sources = response.hits.hits.map(hit =>
hit._source);
if (this.sources.length > 0) {
this.availableMetadata = Object.keys(
this.sources[0].metadata[this.sourceKey]
);
}
});
console.log('hitting')
return this.sources
}
This.sources is reaching as undefined because this.sources is being set in the subscriptioon
The short answer is you cannot cause the code after the subscribe to wait. Having said that, by taking a step back and looking at your code, you should not subscribe within the getGlobeConfig method. What you probably should do is use the map operator within the getGlobeConfig method and let the consumer of the getGlobeConfig method subscribe:
public getGlobeConfig() {
// ...
return this.service.searchQuery(query).pipe(
map(response => {
// Transform the response to what you want
// the consumer of this method to receive
})
);
}
Consumer:
getGlobeConfig().subscribe(sources => /* ... */)
One very common pitfall I am seeing from new RxJs developers is that they try to subscribe to Observables in a service and then want to return the data to the components. In most cases you do not subscribe within the services. Let the services operate on the data within RxJs operators and have the services return the transformed Observables. The end consumer (usually components) will then subscribe to the Observables returned by the services.
Your problem is that you cannot return a synchronous value that is generated in an asynchronous call. The best you can do is return a promise (or other async object). This is what async await is designed to accomplish: it adds keywords that make it easier to wait for promises to finish but in the end you are still working with promises, and async functions always return promises.
Here's some simple examples:
function doSomethingWithPromise() {
return somethingThatReturnsAPromise()
.then((result) => result.calculateSomethingFromResult()) // `then` returns a promise with a result of the callback
}
Transformed to an async call:
async function doSomethingWithAsync() {
// because this is an async function, it returns a promise here, before it finishes waiting
let result = await somethingThatReturnsAPromise()
return result.calculateSomethingFromResult() // at this point, after waiting, the function fulfills the promise with this return value
}
Those two examples are equivalent.
(This is a general example, and if you are using a library that uses streams or events instead of promises, for example, things may be different)

Return result of nested promise success function (Javascript) [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am building a wrapper function to retrieve values stored in a WebExtension's local Storage. I am struggeling to pass the return value of the success function to its outer function. Many thanks in advance!
get(key) {
browser.storage.local.get(key).then(onGot, onError);
function onGot(storage) {
console.log(storage[key]); // Works so far
}
function onError() {
return false;
}
// How can I return storage[key] here?
}
Either return a promise from the wrapper or let your promise resolve and consume the result with a callback.
A promise represents an operation which may or may not have completed yet. It provides hooks for success and failure so that the result of the async operation can be processed.
In order to return from the function, the caller and the executing function should stay in sync (w.r.t control flow). This moves away from async, which is what js promise is for.

MarkLogic NodeJS JavaScript function return [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
Like a person asked here (but his solutions as to call a nother function) https://stackoverflow.com/a/10796326/315200 ...I would like to know if its possible to have a function which doesn't call a second function on response of an async request, but simply return when the async request responses.
Something like this maybe:
function callToFacebook() {
var fbResponse;
FB.api('/me', function (response) {
fbResponse = response;
});
return fbResponse; //Will return undefined because CallToFacebook is async
}
Isn't that possible some way, without calling another function??
What I'm trying to achieve is to have one function I can call with some parameters, which will return the response object from a async webservice, like FB.
In short, no. You cannot have an asynchronous function return a meaningful value synchronously, because that value does not exist at that time (as it is built asynchronously in the background).
You can, however, return a Promise object, representing the "potential return value" of the asynchronous operation, and bind a function to that object using done() or similar. That way, your function gets return semantics (instead of having to chain the control flow into a callback), and remains asynchronous.
No, it's not possible.
You can't return value that is returned from async operation.
Think about it, you tell 10 people to have one mile running contest, they start now, will finish in one minute +-, but you want to know the answer now, it's not possible unless you're cheating...

Categories