Node JS array of Promises still in <pending> [duplicate] - javascript

This question already has answers here:
map() function with async/await
(5 answers)
Closed 2 years ago.
I'd like to do some check on a file with Promises before processing it.
As I'm using Node JS, I'd like to do all the verification asynchronously since they're all independant.
However, I'd like to print all the errors at once (if they are some) for debugging purpose. So I need to wait for all the operation to be done before doing anything else. So I'm using the async/wait keywords.
Here's my code :
async function isValid(file) {
try {
const check = [
check1(file),
check2(file),
check3(file),
check4(file),
check5(file)
]
let results = check.map(async checking => (await checking))
console.log((await results));
} catch(e) {
console.log(e)
}
}
The thing is, what's outputted by the console.log is the following:
[
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
Promise { <pending> }
]
What I expected to get was the result of the checks() function, but they're still pending despite the await keywords present multiple times.
Do you know what's wrong I'm doing?
Thanks in advance.

I think you want to use Promise.all here. You don't actually have to do your .map logic to invoke each individual function and await it. As long as check(<file>) returns a Promise, just call Promise.all on them.
Example:
async function isValid(file) {
try {
const check = [
check1(file),
check2(file),
check3(file),
check4(file),
check5(file)
]
const results = await Promise.all(check);
console.log('results', results);
} catch (e) {
console.log(e)
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Related

How exactly works this async\await code in my Angular application? Why the colled method doesn't explicitly return a Promise?

I am not so into RxJS and I am finding some problems to understand this piece of code retrieved into an Angular project on which I am working.
First of all into a component TypeScript code I have this method:
async post(): Promise<void> {
this.submitted.next(true);
try {
await this.setAddress();
this.activeModal.close();
} catch (e) {
console.error('Storage upload error', e);
this.submitted.next(false);
}
}
As you can see this method have async prefix because into the try block it contains these 2 rows:
await this.setAddress();
this.activeModal.close();
from what I have understand (please correct me if I am doing wrong assertion) basically the await in front of this.setAddress() it means: await that this method call end, when it is completed executed the following operation (that in this case close a modal window).
From what I have understand it replave the then() method handling a Promise resolution. Is it correct or not?
So my doubt is: have my setAddress() method return a Promise? In my specific case setAddress() method is used to call a service method saving some data on the database and have this code:
async setAddress(): Promise<void> {
try {
const c: Address = {
companyName:this.addressFormGroup.get('companyName').value,
street: this.addressFormGroup.get('street').value,
city: this.addressFormGroup.get('city').value,
zipCode: this.addressFormGroup.get('zipCode').value,
notes: this.addressFormGroup.get('notes').value,
};
//save/update record
await this.userService.setUserAdresss(this.currentUserUID,this.addressType,c);
this.success = true;
if (!this.isEditMode) {
this.addressFormGroup.reset();
}
} catch (e) {
console.error(e);
} finally {
this.submitted.next(false);
}
}
And here I have a lot of doubts on how it works...ok the method signature:
async setAddress(): Promise<void> {
seems to return a Promise (why ? what it means?). But where is it effectivelly returning a Promise? In the code of this method I can't find that it is returning a Promise nowhere. It seems to me that it is returning nothing because it is not containing the return statement !!!
My only interpretation is the following one (but it is my idea and probably totally wrong): also if it is not explicitly returning nothing it have a Promise as method returned type. So it means that at the end of the method execution TypeScript automatically return an "empty" Promise that simply means: "method execution completed".
I am absolutly not sure, this is the only explaination that I can give to this code.
How it wxactly works?
Your assumptions are correct.
A function declared with the async keyword will return a Promise that is completed when the function has finished its execution.
The await keyword is equivalent to using the then method with the remaining lines of codes as the callback function.
Using try/catch/finally arround an await is equivalent to using the catch/finally method on the promise.
This is your code written with promises instead of async/await :
post(): Promise<void> {
this.submitted.next(true);
return this.setAddress()
.then(() => this.activeModal.close())
.catch((e) => {
console.error('Storage upload error', e);
this.submitted.next(false);
});
}
setAddress(): Promise<void> {
const c: Address = {
companyName:this.addressFormGroup.get('companyName').value,
street: this.addressFormGroup.get('street').value,
city: this.addressFormGroup.get('city').value,
zipCode: this.addressFormGroup.get('zipCode').value,
notes: this.addressFormGroup.get('notes').value,
};
//save/update record
return this.userService.setUserAdresss(this.currentUserUID,this.addressType,c)
.then(() => {
this.success = true;
if (!this.isEditMode) {
this.addressFormGroup.reset();
}
})
.catch((e) => console.error(e))
.finally(() => this.submitted.next(false));;
}

Why does my async function always return a pending promise? [duplicate]

This question already has answers here:
async/await implicitly returns promise?
(5 answers)
Closed 1 year ago.
When I console.log(data), I log the information I need, but if return the value of data in getWeather(), it just returns a pending promise. I have tried many things, but none have worked so far. I'll leave my broken code below.
const axios = require('axios');
const getWeather = async () => {
try {
let response = await axios.get(
'http://api.openweathermap.org/data/2.5/forecast?id=524901&appid={apiKey}'
);
let data = response.data;
return data;
} catch (e) {
console.log(e);
}
};
async function returnAsync() {
const x = await getWeather();
return x;
}
console.log(getWeather()); // returns a pending promise
console.log('check ', returnAsync()); // also returns a pending promise
async functions must return a promise. (they implicitly return Promise<void> instead of void!)
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
For example, the following:
async function foo() {
return 1
}
...is equivalent to:
function foo() {
return Promise.resolve(1)
}
Source
This could be to do with the fact that you're trying to call an async function inside of a synchronous function. It's quite a common mistake to make, so don't fret. Typically if you think about the structure, the console logs could technically be run before the async function has completed. That's why we have "callback functions" which basically just run as soon as the async returns a value.
Axios has a really neat way to use these callbacks which is just using the .then() function.
So try this out and see if it works:
const axios = require('axios');
const getWeather = async () => {
axios.get('http://api.openweathermap.org/data/2.5/forecast?id=524901&appid={apiKey}')
.then(json => console.log(json))
.catch(error => console.log(error))
};
getWeather();
Because you're trying to call the get request inside of an async function, you cannot then grab the data in a synchronous function.
//const getWeather = async () => {...
An async function's return value will be 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.
check more at
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

Async function returning pending promise, despite use of await [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
async/await implicitly returns promise?
(5 answers)
Closed 3 years ago.
In the below code snippet I am trying to understand why the function does not return the result of the promise.
It first logs Promise { <pending> }, then logs the response variable with the correct data from the AWS API describing the table.
Why is it doing this? I've tried wrapping the function in another async function and awaiting it and I get the same result.
const AWS = require('aws-sdk');
AWS.config.update({region: 'eu-west-2'});
const docClient = new AWS.DynamoDB;
async function describeTable() {
const params = {
TableName: 'weatherstation_test',
};
let response;
try {
response = await docClient.describeTable(params).promise();
console.log(response); // This logs second. It logs the data correctly
} catch (e) {
console.error(e)
throw e;
}
return response;
}
console.log(describeTable()); // This logs first. It logs Promise { <pending> }
Update
This still returns Promise { <pending> } even if I add .then(result => result).

Can't get the fetched data from JSON file into new function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
Im still kinda new to Javascript. Right now I'm building a web application where I want to show items from a data.json file and search through those items.
I have a fetchItems() function where I fetch the data.json. After this I show the items in the index.html with the initItems() function.
The problem is that I want those 'items' from the fetch call available in the searchItems() function too. With these 'items' I plan to filter the items. Unfortunately I'm missing something which is why the console.log in searchItems.js gives back undefined.
I tried different things with async and await but couldn't get that to work either.
index.js
import { fetchItems } from "./src/js/fetchItems";
import { searchItems } from "./src/js/searchItems";
fetchItems();
searchItems();
fetchItems.js
export function fetchItems() {
return fetch("./src/data/data.json")
.then(response => response.json())
.then(items => initItems(items));
}
function initItems(items) {
for (let item of items) {
let appItem = document.createElement("app-item");
let appItems = document.getElementById("app-items");
appItems.appendChild(appItem);
appItem.setAttribute("name", item.name);
appItem.setAttribute("description", item.description);
}
}
searchItems.js
export function searchItems(items) {
console.log(items);
}
I would do this :
index.js
import { fetchItems } from "./src/js/fetchItems";
import { searchItems } from "./src/js/searchItems";
async function fetchAndSearch() {
const items = await fetchItems();
searchItems(items);
}
fetchItems.js
async function fetchItems() {
const response = await fetch("./src/data/data.json");
const items = await response.json();
initItems(items);
return items;
}
If you begin with JavaScript, I think async/await syntax is the way to go.
fetchItems is asynchronous, so trying to call search items right away will not work, because fetchItems will not have finished yet. Fortunately, fetchItems is returning a promise, so you're almost there. A promise is a representation of an eventual value. To get notified when that promise is done resolving, use it's .then method. For example:
fetchItems()
.then(() => searchItems());
Async/await can make the syntax cleaner, but it's still using promise. To do the same thing using async await would look something like the following (The code needs to be in an async function, so i created one):
async function doStuff() {
await fetchItems();
searchItems();
}

JavaScript - async/await not waiting for promise to resolve [duplicate]

This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 5 years ago.
I want to use Mongoose's bulk operation for upserting transactions. For each of my transactions I want to process them in a loop and within that loop I need to use a promise. After that promise resolved, I want to add the upsert to the bulk.
My problem here is, that although I await for every promise to finish, the bulk is executed at the end of the function before any of the promises is resolved. What am I doing wrong or how can I fix this?
const bulkTransactions = Transaction.collection.initializeUnorderedBulkOp();
transactions.forEach( async (transaction: any) => {
// do some suff, fill transaction_data
await Utils.processTransactionType(transaction).then((action: any) => {
if (action) {
// do other stuff
}
bulkTransactions.find({_id: hash}).upsert().replaceOne(transaction_data);
}).catch((err: Error) => {
// log error
});
});
await bulkTransactions.execute().catch((err: Error) => {
// log error
});
As far as I know, when using await, you no longer use the then return value:
const bulkTransactions = Transaction.collection.initializeUnorderedBulkOp();
transactions.forEach( async (transaction: any) => {
// do some suff, fill transaction_data
let action = await Utils.processTransactionType(transaction);
if (action) {
// do other stuff
}
bulkTransactions.find({_id: hash}).upsert().replaceOne(transaction_data);
});
await bulkTransactions.execute().catch((err: Error) => {
// log error
});

Categories