Reputation: 155
I have a filter method as follows:
let newArray = Alerts[symbol].filter(async (alert: IDiscordSymbolAlert, alert_index: number) => {
// If Price when set is greater than alert price, price has to move UP to trigger
if (alert.price_when_set < alert.alert_price) {
hasToGo = Change.UP;
}
// If Price when set is greater than alert price, price has to move DOWN to trigger
else if (alert.price_when_set > alert.alert_price){
hasToGo = Change.DOWN;
}
/**If the hasToGo is UP and current price is greater than alert price, then ALERT USER [OR]
// If the hasToGo is DOWN and current price is lesser than alert price, then ALERT USER **/
if((hasToGo === Change.UP && (price >= alert.alert_price)) ||
(hasToGo === Change.DOWN && (price <= alert.alert_price))) {
/**
* Send Notification that alert has been hit
*/
let userToSend = await discord.users.fetch(alert.userID)
if(!userToSend) return;
//@ts-ignore
userToSend.send(`> @everyone\n\n${symbol} has reached your alert price - ${alert.alert_price}`);
// remove that alert
guild_modified = true;
return false;
}
return true;
});
// When logged here, it shows the entire array even though certain values have returned false.
// I know they returned false because the block in which they returned false was executed and
//i did receive a notification which was executed in the same block.
console.log(newArray);
When logged here (console.log)
, it shows the entire array even though certain values have returned false. I know they returned false because the block in which they returned false was executed and i did receive a notification which was executed in the same block. I know this has something to do with the async/await
, but i'm not exactly sure what. Can someone please take a look.
updated question
Alerts[symbol].forEach(async (alert: IDiscordSymbolAlert, alert_index: number) => {
// If Price when set is greater than alert price, price has to move UP to trigger
if (alert.price_when_set < alert.alert_price) {
hasToGo = Change.UP;
}
// If Price when set is greater than alert price, price has to move DOWN to trigger
else if (alert.price_when_set > alert.alert_price){
hasToGo = Change.DOWN;
}
/**If the hasToGo is UP and current price is greater than alert price, then ALERT USER [OR]
// If the hasToGo is DOWN and current price is lesser than alert price, then ALERT USER **/
if((hasToGo === Change.UP && (price >= alert.alert_price)) ||
(hasToGo === Change.DOWN && (price <= alert.alert_price))) {
/**
* Send Notification that alert has been hit
*/
let userToSend = await discord.users.fetch(alert.userID)
if(!userToSend) return;
//@ts-ignore
userToSend.send(`> @everyone\n\n${symbol} has reached your alert price - ${alert.alert_price}`);
// remove that alert
Alerts![symbol].splice(alert_index, 1);
guild_modified = true;
}
});
console.log(Alerts[symbol]);
Since filter cannot be used in this case with async/await
. This is me using forEach()
loop and manually deleting the matched object in the array using splice()
. But since the forEach itself is asynchronous and the console.log
is acting outside the async block. It's not returning the new array, rather the unmodified one. How can i return the new array to be used outside the scope of the forEach block.
Thanks in advance!
Upvotes: 0
Views: 522
Reputation: 1074138
You can't use an async
function with filter
. filter
returns all elements for which the callback returns a truthy value. async
functions always return promises, which are objects, and all non-null
objects are truthy.
If your filter
check needs to be async
, your entire operation is async
and needs to be handled as such.
Here's an off-the-cuff async
filtering function that does the element checks in parallel. Again, like all async
functions, it returns a promise of its result:
async function filterAsync(array, callback, thisArg = undefined) {
const flags = await Promise.all(array.map(callback, thisArg));
const result = [];
for (let n = 0; n < array.length; ++n) {
if (flags[n]) {
result.push(array[n]);
}
}
return result;
}
To use that, you have to consume the promise:
// In an `async` function (assuming you want errors to propagate):
const newArray = await filterAsync(Alerts[symbol], element => /*...keep-or-toss logic...*/);
// ...use `newArray`...
or
// Not in an `async` function
filterAsync(Alerts[symbol], element => /*...keep-or-toss logic...*/)
.then(newArray => {
// ...use `newArray`...
})
.catch(error => {
// ...handle/report error...
});
Upvotes: 7