Void.delete() (discord.JS v13) - javascript

so I know the problem, I just dont know a solution for this.
The console.log says: TypeError: msg.delete is not a function
I know msg is a void, so thats why it doesnt work.
Im thankful for every help!
My code looks like this:
message.channel.bulkDelete(messages);
message.channel.send("Messages getting purged...")
.then((sentMessage) => setTimeout(function () {
sentMessage.edit(` **${amount}** messages were purged!`)
}))
.then((msg) => setTimeout(function () { msg.delete() }, 6000)

message.channel.bulkDelete(messages);
message.channel.send("Messages getting purged...")
.then((sentMessage) => setTimeout(function () {
sentMessage.edit(`**${amount}** messages were purged!`).then((msg) => setTimeout(function () { msg.delete() }, 6000)
}))

The problem is msg is not the message you sent, but the timeout ID as you return it here: (sentMessage) => setTimeout().
Try to return the sentMessage so you an grab it in your next then():
message.channel
.send('Messages getting purged...')
.then(sentMessage => {
setTimeout(function () {
sentMessage.edit(` **${amount}** messages were purged!`);
});
return sentMessage;
})
.then(msg =>
setTimeout(function () {
msg.delete();
}, 6000),
);
It would be probably better to use async/await here though (just make sure you're inside an async function):
try {
// send a message that messages are being deleted
const sentMessage = await message.channel.send('Messages getting purged...');
// delete the messages and wait for them to be deleted
const deletedMessages = await message.channel.bulkDelete(messages);
// edit the sent message when finished
await sentMessage.edit(`**${deletedMessages.size}** messages were purged!`);
// delete the message after 6 seconds
setTimeout(() => sentMessage.delete(), 6000);
} catch (err) {
message.channel.send(`Oops, there was an error`);
console.log(err);
}

Related

Lambda function running code first run but not subsequent runs

I have a Node.js Lambda function that during the inital run ran fine, however during the subsequent runs - 1 minute interval - it is completing in about 1.5ms and not running my code at all other than outputting finished - the console.log in my then block.
What would the reason for this be?
module.exports.perf = function(event, context, callback) {
context.callbackWaitsForEmptyEventLoop = false;
let input = JSON.parse(event.Records[0].body);
const point1 = new Point('elapsedTime')
.tag(input.monitorID, 'monitorID')
.floatField('elapsedTime', input.perf_value)
writeApi.writePoint(point1)
writeApi
.close()
.then(() => {
console.log('FINISHED ... ')
})
.catch(e => {
console.error(e)
if (e instanceof HttpError && e.statusCode === 401) {
console.log('Run ./onboarding.js to setup a new InfluxDB database.')
}
console.log('\nFinished ERROR')
})
return
};
EDIT**
const writeApi = new InfluxDB({url: InfluxURL, token}).getWriteApi(org, bucket, 'ms')```
I ended up coming up with a solution thanks to someone elsewhere online and the result was changing .close() to .flush() in the following code
writeApi
.flush() # used to be .close()
.then(() => {
console.log('FINISHED ... ')
})

socket.io and async events

I'm using socket.io and mongoose in my express server.
My socket is listening for events using the following code:
socket.on('do something', async () => {
try {
await doA();
doX();
await doB();
doY();
await doC();
} catch (error) {
console.log(error);
}
});
doA, doB and doC are async operations that writes on database using mongoose, but in general they can be any method returning a promise.
I want that 'do something' runs synchronously.
If the event queue processes more events at the same time I have consistency problems in my mongodb.
In other words if the server receives two 'do something' events, I want that the second event received is processed only when the first event is fully processed (after the await doC). Unfortunately the 'do something' callback is async.
How to handle this?
It's possible to implement a queue by adding the functions you want to run to an array, and then running them one by one. I've created an example below.
let queue = [];
let running = false;
const delay = (t, v) => {
return new Promise((resolve) => {
setTimeout(resolve.bind(null, "Returned value from Promise"), t)
});
}
const onSocketEvent = async () => {
console.log("Got event");
if (!running) {
console.log("Nothing in queue, fire right away");
return doStuff();
}
// There's something in the queue, so add it to it
console.log("Queuing item")
queue.push(doStuff);
}
const doStuff = async () => {
running = true;
const promiseResult = await delay(2000);
console.log(promiseResult);
if (queue.length > 0) {
console.log("There's more in the queue, run the next one now")
queue.shift()();
} else {
console.log("Queue empty!")
running = false;
}
}
onSocketEvent();
setTimeout(() => onSocketEvent(), 1000);
setTimeout(() => onSocketEvent(), 1500);
setTimeout(() => onSocketEvent(), 2000);
setTimeout(() => onSocketEvent(), 2500);
I would suggest adding a delay between each await. This will prevent deadlocks from occurring and fix your issue. For such things, I would suggest using the Caolan's async library.
Task delay example:
setTimeout(function() { your_function(); }, 5000); // 5 seconds
If your function has no parameters and no explicit receiver, you can call directly setTimeout(func, 5000)
Useful jQuery timers plugin

Stop next execution of Rxjs observer?

I am trying with the basic use case of a Rxjs observer. This is what I am doing:
const { Observable } = require('rxjs');
Observable.create(o => {
setTimeout(() => o.next('hi'), 1000);
setTimeout(() => { throw new Error('A mistake') }, 1500);
setTimeout(() => o.next('this should not print'), 2000) }
).subscribe({
next: x => console.log(x),
error: y => console.log('error', y),
complete: () => console.log('done')
});
The out put of this is the following:
> hi
Error: A mistake
at Timeout.setTimeout [as _onTimeout] (repl:1:89)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
> this should not print
What I need to do is stop the execution of the next, and even If I unsubscribe my subscription it is not stopping the next execution.
I tried like this too:
let subscription;
let source = Observable.create(o => {
try {
setTimeout(() => o.next('hi'), 1000);
setTimeout(() => { throw new Error('A mistake') }, 1500);
setTimeout(() => o.next('this should not print'), 2000)
} catch (e) {
subscription.unsubscribe();
return 'error';
}
});
subscription = source.subscribe({
next: x => console.log(x),
error: y => console.log('error', y),
complete: () => console.log('done')
});
but no chance... it did not stop.
What I have as code is not just set timeout I have async and await code like this:
let subscription;
let source = Observable.create(async o => {
try {
o.next(await anEvent());
o.next(await anEventThatThrowsAnException());
o.next(await anEventThatIWantToAvoidDueToTheException());
} catch (e) {
subscription.unsubscribe();
return 'error';
}
});
subscription = source.subscribe({
next: x => console.log(x),
error: y => console.log('error', y),
complete: () => console.log('done')
});
How can I achieve this code to stop the "this should not print" ?
After you set the timer with setTimeout, you will not prevent it's execution with unsubscribe.
You will need to manually clear your timeouts.
Note that you can save your timeouts in variables var myTimeout = setTimeout(f,ms); then you can cancel then clearTimeout(myTimeout);
Read More:
setTimeout
clearTimeout
This is the way to make it work with observer.error as stated by ABOS. In fact this is his example and it works.
So Just for documentation purposes I answered this question with his answer from the comment.
ABOS answer
I just thought that if someone is having problem trying to handle errors throwing the error instead of catching and executing observer.error in the way that is needed.

Asynchronous Function Halting Synchronous Function

So I have a synchronous function (client.functionOne) that is creating a Discord.js message collector, which deletes messages sent to a channel. This function also calls an asynchronous function which creates a setTimeout loop.
The issue is, for some reason, the "collect" function gets held up whenever the code in client.functionTwo is run and it does not run as fast as it would if it wasn't running.
I am unsure why it is doing this. Could someone please help? Thanks in advance.
client.functionTwo = async (channel) => {
let timeout;
const interval = async () => {
// Logic here with several awaits
// Schedule a new timeout
timeout = setTimeout(interval, 2000);
}
interval();
}
client.functionOne = (channel) => {
setTimeout(() => {
const collector = channel.createMessageCollector(() => true, { time: 150000 });
client.functionTwo(channel);
collector.on("collect", (message) => {
if (message.author.bot) return;
message.delete();
});
}, 1000);
}
// client.functionTwo = async (channel) => {
// let timeout = await setTimeout(interval, 2000);
// }
client.functionOne = async (channel) => {
const collector = await channel.createMessageCollector(() => => true,
{ time: 150000 });
// await client.functionOne(channel);
collector.on("collect", async (message) => {
if (message.author.bot) return;
await message.delete();
});
}
After extensive testing I was able to determine that my issue was caused by rate limiting with Discord and the JavaScript library I am using.

Express: Does my code still run even after a response is sent?

I have code that basically looks like this:
return Promise.all([
myPromise("foo", () => saveToFirebase("foo")),
myPromise("bar", () => saveToFirebase("bar")),
... // 50 more of these ^
]).then(() => {
res.status(200).send('ok');
}).catch(err => {
console.log(err.stack);
res.status(500).send('error');
});
My request times out because some of my requests take a long time. My question is: if I just called res.status(200) without chaining it Promise.all, would my unresolved promises still resolve even after a response is sent? Or would all execution of my code stop once a response is sent?
Like this:
Promise.all([
myPromise("foo", () => saveToFirebase("foo")),
myPromise("bar", () => saveToFirebase("bar")),
... // 50 more of these ^
])
res.status(200).send('ok');
The promise will always be executed. As you can see in following picture after response is send after promise resolve is printed on console.
And you can also keep the connection alive by setting res.shouldKeepAlive to true like this :
Promise.all([
check(2),
check(2),
check(2)
]).then(() => {
console.log('after promise resolve');
setTimeout(function() {
res.send('done');
}, 10000);
});
console.log('Before promise resolve');
res.shouldKeepAlive = true;
All promises will be either resolved or rejected. Express does not stop any execution when you finish request. You can try it out by simple console log:
Promise.all([
myPromise("foo", () => saveToFirebase("foo")),
myPromise("bar", () => saveToFirebase("bar")),
... // 50 more of these ^
])
.then(() => console.log("promises resolved"))
.catch(err => console.error("promises rejected", err))
res.status(200).send('ok')
However with this approach you don't know if anything went wrong when sending response.
Alternatively you could keep the connection alive like this:
const keepalive = setInterval(_=>res.write("."),1000);
return Promise.all([
myPromise("foo", () => saveToFirebase("foo")),
myPromise("bar", () => saveToFirebase("bar")),
... // 50 more of these ^
]).then(() => {
res.status(200).send('ok');
}).catch(err => {
console.log(err.stack);
res.status(500).send('error');
}).then(_=>clearInterval(keepalive));

Categories

Resources