I read like through 10 pages on how to resolve promises but i still don't get it.
Info: I want to fetch a specific member of a discord server
Currently I have a async function with the promise inside that returns it but it gives me a message with "Invalid Body Form"
async function mbr() {
const mB = await client.guilds.cache.get("1037783624449282189").members.fetch(`${args[0]}`).then((m) => { return m; });
return mB
}
let member = mbr()
if (member.roles.cache.has("1039983830389510305"))
Edit: It gives me this Error when i do a async Function inside a async function
G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\node_modules\#discordjs\rest\dist\index.js:659
throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
^
DiscordAPIError[50035]: Invalid Form Body
user_id[NUMBER_TYPE_COERCE]: Value "undefined" is not snowflake.
at SequentialHandler.runRequest (G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\node_modules\#discordjs\rest\dist\index.js:659:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async SequentialHandler.queueRequest (G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\node_modules\#discordjs\rest\dist\index.js:458:14)
at async REST.request (G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\node_modules\#discordjs\rest\dist\index.js:902:22)
at async GuildMemberManager._fetchSingle (G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\node_modules\discord.js\src\managers\GuildMemberManager.js:489:18)
at async mbr (G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\chatBridge\accountLink.js:8:32)
at async G:\Desktop\Minecraft Modding\Bedrock\_____\Server\legend\plugins\nodejs\discord-bot\chatBridge\accountLink.js:11:30 {
requestBody: { files: undefined, json: undefined },
rawError: {
code: 50035,
errors: {
user_id: {
_errors: [
{
code: 'NUMBER_TYPE_COERCE',
message: 'Value "undefined" is not snowflake.'
}
]
}
},
message: 'Invalid Form Body'
},
code: 50035,
status: 400,
method: 'GET',
url: 'https://discord.com/api/v10/guilds/1037783624449282189/members/undefined'
}
Promises need to be awaited, either by using p.then(callback), or by using await p.
For example, this Promise:
const p = new Promise(resolve => setTimeout(resolve("Hello world!"), 100));
will resolve in 100 ms, and can be used either like this
p.then(message => console.log(message));
or like this
console.log(await p);
In short, your function:
async function mbr() {
const mB = await client.guilds.cache.get("1037783624449282189").members.fetch(`${args[0]}`).then((m) => { return m; });
return mB
}
can be resolved by either
mbr().then(member => {
if (member.roles.cache.has("1039983830389510305")) { ... }
});
or
const member = await mbr();
if (member.roles.cache.has("1039983830389510305")) { ... }
Note that in order to use await, you must be in an async context! By default, Node.js's global scope is synchronous, so you need to wrap your code inside an anonymous async function, like so:
(async () => {
const member = await mbr();
if (member.roles.cache.has("1039983830389510305")) { ... }
})(); // <-- call immediately
You have three ways to accomplish this:
Top-level await
Note: If this is an option in your JavaScript runtime.
let member = await mbr();
if (member.roles.cache.has("1039983830389510305")) {
// ...
}
IIFE async
(async () => {
let member = await mbr();
if (member.roles.cache.has("1039983830389510305")) {
// ...
}
})();
Promise resolution
mbr()
.then((member) => {
if (member.roles.cache.has("1039983830389510305")) {
// ...
}
});
Also, your mbr function can be simplified to:
const mbr = async () =>
client.guilds.cache
.get("1037783624449282189").members
.fetch(`${args[0]}`)
async/await can be used to make the code for working with promises a lot more concise and readable.
In case you don't know how promises work, here's a quick explanation:
Promises are a way for developers to create asynchronous, non-blocking code that will run "at the same time" as the current code. All promises should eventually resolve or reject, which are callbacks that let developers run extra code after a promise is finished.
In Discord specifically, fetching members creates an api request, which could take any amount of time, so it returns a promise. In order to actually use the data from the promise, you have to retrieve the data after it's resolved, which can be easily accomplished with async/await.
// since this function is async, it will ALWAYS return a promise
async function mbr() {
// await can be used to pause code execution until the promise resolves
// you don't need to use `.then()`, because await is already resolving your promise
const mB = await client.guilds.cache.get("1037783624449282189").members.fetch(`${args[0]}`);
// return the resolved value of the promise
return mB
}
// you need to add await here, because mbr() now returns a promise itself
// make sure this code is placed in an async function or use top level awaits
let member = await mbr()
// you can now use the member object and the data it contains
if (member.roles.cache.has("1039983830389510305"))
Hope this helps.
async function mbr() {
const mB = await client.guilds.cache.get("1037783624449282189").members.fetch(`${args[0]}`).then((m) => { return m; });
return mB
}
let member = await mbr()
if (member.roles.cache.has("1039983830389510305"))
Related
So I am creating a module with a class method(schedule) with async function awaiting the return
//SCHEDULER.JS//
class Schedule {
constructor(project_id, queue_id) {
this.project_id = project_id;
this.queue_id = queue_id;
}
//ASYNC METHOD 1
schedule = async (date, rquest) => {
const project = this.project_id;
const queue = this.queue_id;
const location = "us-central1";
const url = rquest.url;
const payload = rquest.body;
// Construct the fully qualified queue name.
const parent = client.queuePath(project, location, queue);
const task = {
httpRequest: {
httpMethod: rquest.method,
url,
headers: rquest.headers,
},
};
try {
const request = await { parent, task };
const [response] = await client.createTask(request);
console.log("<THIS IS THE PROJECT ID> :", response.name);
return `${response.name}`;
} catch (error) {
console.log("we have an error amigo!", error);
}
};
//ASYNC METHOD 2
delete = async (one) => {
return console.log("delete function", one);
};
I imported my module on main.js and used my method. Once the results returns, I need to use it as a parameter to another method(delete) on the module I created(Scheduler.js).
//main.js//
const task_id = scheduler.schedule(date, request);
scheduler.delete(task_id);
task_id is returning a promise and I can't execute scheduler.delete(task_id) because it is pending promise still.
Important: How can I handle this promise properly as I am only tasked to create the module and not the main.js. The people who would create the main.js would just be expected to run my methods without handling promise returns.
TLDR
task_id is returning a promise
If it's a promise you can await it
//main.js//
async function main () {
const task_id = await scheduler.schedule(date, request); // <--- THIS!
scheduler.delete(task_id);
}
main();
Await & promises:
In fact, the await keyword only works on promises (you can await non-promises but it is a no-op by design). That's the whole reason for await - an alternative way to use promises. Because of this functions marked with the async keyword always returns a promise.
Or if you prefer not to await then just use it as a promise:
//main.js//
scheduler.schedule(date, request)
.then(task_id => scheduler.delete(task_id));
You can create another function, which will be called from main.js, and inside this function call your actual function and in then function of Promise return the value.
Given the following code:
async #token() {
const value = await this.belcorp.getAccessToken();
console.log(value);
}
This code returns:
But if I try to return that same result in my constructor with this code:
constructor() {
const token = this.#token();
console.log(token);
}
async #token() {
return await this.belcorp.getAccessToken();
}
returns the following:
What should I do to retrieve only the previous object?
Aside from the issue of Promises in constructors, your code returns a Promise because that is what you told it to do: async functions return Promises. If you want the awaited Promise result instead, change the line to
const token = await this.#token();
Of course, you would need your constructor to be async in this case, so you will need to move your code outside your constructor.
You cannot make a class constructor async. Instead, just make your own static constructor method -
class MyThing {
constructor(token) { // cannot be async
this.token = token // make sync instead
}
static async token() { // make static
return new Promise(r =>
setTimeout(r, 1000, "tkn123") // demo token response
)
}
static async new () { // make async constructor
return new MyThing(await this.token()) // await token
}
}
const main = async () =>
{ console.log("loading...")
const x = await MyThing.new() // <-- MyThing.new()
console.log("got token:", x.token)
return "done"
}
main().then(console.log, console.error)
// loading...
// got token: tkn123
// done
(Forgive me if the title is inaccurate to the problem this one is boggling the mind)
My application requires that I check a value from the request against the database. For this I created an asynchronous function to query the database:
async function checktoken(){
return prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
return(result)
})
}
I know that the database call on its own works:
prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
console.log(result) // returns true
})
In the function that fires at every request I try and call checktoken():
async function getUser(token){
var promise = await checktoken()
var result = promise
console.log(result) //undefined
};
Amending the function to include an explicit call to the database works but only when var promise = await checktoken() is defined before it:
async function getUser(token){
var promise = await checktoken() //When this is removed result1 is undefinded
await prisma.$exists.invalidtoken({token: "testtoken"}).then(result1 => {
console.log("inside db call: "+result1) // true
})
};
I think I have a fundamental misunderstanding of async/await but I am not sure exactly what I am missing.
EDIT:
I have updated my approach taking the advice I received and it still does not work. I am beginning to think my ORM is doing something weird:
async function test(token) {
const status = await prisma.$exists.invalidtoken({ token: token });
console.log(status);
return status;
}
test("123") //logs false (as it should)
async function getUser(token){
var status = await test(token) //logs undefined
console.log(status) //logs undefined
};
An async function requires an await. If you are using the promise.then() technique, then what you would want to do is return a new Promise(), and within the .then call back function resolve the promise
function checktoken() {
return new Promise((resolve,reject) => {
prisma.$exists.invalidtoken({token: "testtoken"}).then(result => {
doSomeOtherStuff();
resolve(result);
});
});
}
Is functionally the same as
async checktoken() {
await prisma.$exists.invalidtoken({token: "testtoken"});
}
I'm trying to make this code (a class method) returning a String.
async sign() {
const txt = 'ddddd';
const result = await crypto.createHash('md5').update(txt, 'binary').digest('hex');
return result;
}
The problem is that it ignores await and returns a Promise. This function's returned value is used as a HTTP request header, and while npmlog says it's
apisign: Promise { 'faaa3f1409977cbcd4ac50b5f7cd81ec' }
in network traffic caught by Wireshark I see
apisign: [object Promise]
How do I make return respecting await, or how should I write it so it returns a String?
You should not return the value of an async function as is, since it is a Promise
await for it before serializing it.
An async function always returns a Promise.
If you invoke sign() inside another function then you have to await for it and this requires making the caller function also an async function and so on and so forth.
Eventually, at the top-level code you have to use the regular .then().catch() syntax to wait for the Promise to settle:
sign()
.then((result) => {
// do something with the result (e.g. put it into the response header)
console.log(result);
})
.catch((err) => {
// something wrong happened and the Promise was rejected
// handle the error
console.log(`There was an error: ${err.message || err}`);
});
You will have to await the response of a async function.
const getURL = (title, page) => `https://jsonmock.hackerrank.com/api/movies/search/?Title=${title}&page=${page}`
const callService = async (title, page) => {
let response = await fetch(getURL(title, page));
return await response.json();
}
async function callApi() {
let data = await callService('spiderman', 1);
console.log(data.data.length);
}
callApi();
In my case , i am able to get the token but not the way i wanted ie i do not want to print promise pending and my output after running in tokenDisp.js is :
output: Promise { pending }
t5Npxk5FfnRTj8iHd8vyyfGxnhXR4KQf
login.js:
module.exports = async function doLogin() {
const token = await loginToken();
const myToken = JSON.parse(token);
return console.log(myToken);
};
tokenDisp.js:
const myToken = require('./login.js);
myToken();
Can someone help ?
All async functions return a promise and you still have to use .then() or await on the return value from the async function in order to use that. If you return a value from your async function, it will be the resolved value of the returned promise. If you throw an exception, the exception will be the reason for the rejection of the returned promise.
The use of await inside the function is a convenience INSIDE the async function. It does not magically make an asychronous operation into a synchronous one. So, your function returns a promise. To get the value out of it, use .then() on it.
module.exports = async function doLogin() {
const token = await loginToken();
const myToken = JSON.parse(token);
console.log(myToken);
return myToken; // this will be resolved value of returned promise
};
const myToken = require('./login.js);
myToken().then(token => {
// got token here
}).catch(err => {
console.log(err);
});
Note: your login.js module produces the same result as if it was written like this (without using async or await):
module.exports = function doLogin() {
return loginToken().then(token => {
const myToken = JSON.parse(token);
console.log(myToken);
return myToken; // this will be resolved value of returned promise
});
};