How to ensure a promise has resolved [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
How do I ensure a promise has resolved in my configuration file. For example my configuration looks like the below.
const fetch = require("node-fetch");
const fetchToken = async () => {
return await fetch('www.token-endpoint.com', {
method: "POST",
headers: {
ContentType: "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
secret: "this is a secret",
})
})
}
const ACCESS_TOKEN = fetchToken()
.then((res) => { return res.json() })
.then(...)
// And so on
// Now I want my promise to definitely resolve
module.exports = {
accessToken: ACCESS_TOKEN // This will be undefined unless my promise has resolved
}
After this I would like to use the token.
const config = require("./config")
// Use config.accessToken knowing it is well defined.

you can do something like this ,node fetch actually has
a built in function for converting the response to JSON, but it does not do it automatically in the same way that Axios and SuperAgent do. recent versions of this library use promises, so we're able to use async/await syntax with it as well:
const fetch = require('node-fetch');
(async () => {
try {
const response = await fetch('www.token-endpoint.com')
const json = await response.json()
console.log(json.url);
console.log(json.explanation);
} catch (error) {
console.log(error.response.body);
}
})();

Related

testing fastapi response to next.js with fetch, promise stuck in pending?

my fetch is stuck in pending when I query a fastapi endpoint in local dev.
followed this blog and a few others - https://damaris-goebel.medium.com/promise-pending-60482132574d
Using this fetch code (having simplified it drastically just to get a simple solution working)
function fastapiRequest(path) {
return fetch(`${path}`)
.then((response) => {
return response;
}
);
into a constant variable i.e.,
const xxxx = fastapiRequest(
`http://0.0.0.0:8008/xcascasc/Dexaa/Emo.json?Magic=Dexxaa&emotion=expressions`
);
Ideally I want to use UseSWR to do this as I'm using next.js, but first of all, just need it to work :)
A postman query like this works fine to return a value
curl --location --request GET 'http://0.0.0.0:8008/xcaxc/dexxa/emo.json?analysis=statistical&substance=dexxa&emo=powa' \
--header 'x_token: 13wdxaxacxasdc1'
the value is left like this in console.log
data show here? Promise {<pending>}
With the initial response being
Response {type: 'cors', url: 'url', redirected: false, status: 200, ok: true, …}
Update based on answers.
Using each of the proposed answers, I am still not getting the data returned appropriately. i.e.,
function fastApiRequest(path) {
console.log("really begins here");
return fetch(`${path}`, { mode: 'cors' })
.then((response) => {
console.log('response', response);
return response.json();
})
.catch((err) => {
throw err;
});
}
async function test() {
console.log('begins');
return await fastApiRequest(
`http://0.0.0.0:8008/xxxx/dex/adea.json?deaed=adedea&adee=deaed&adeada=adeeda`
);
}
const ansa = test();
Is giving a response of pending at the moment.
The backend is built with fastapi, with these CORS, I'm wondering if I need to give it more time to get the data? (postman works fine :/)
def get_db():
try:
db = SessionLocal()
yield db
finally:
db.close()
origins = [
"http://moodmap.app",
"http://localhost:3000/dashboard/MoodMap",
"http://localhost:3000",
"http://localhost",
"http://localhost:8080",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
max_age=3600,
)
I am running the fastapi code in a docker container as well btw
As per Documentation
The Response object, in turn, does not directly contain the actual JSON response body but is instead a representation of the entire HTTP response. So, to extract the JSON body content from the Response object, we use the json() method, which returns a second promise that resolves with the result of parsing the response body text as JSON.
.json() is an async method (it returns a Promise itself), so you have to assign the parsed value in the next .then(). So your code can be changed like this.
function fastApiRequest(path) {
let res;
fetch(`${path}`)
.then((response) => response.json())
.then((data) => (res = data))
.then(() => console.log(res));
return res;
}
response = fastApiRequest('https://proton.api.atomicassets.io/atomicassets/v1/accounts?limit=10');
console.log('response')
If you want to use async/await approach, below is the code.
async function fastApiRequest(path) {
try {
const response = await fetch(path);
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
}
async function test() {
console.log(await fastApiRequest('https://proton.api.atomicassets.io/atomicassets/v1/accounts?limit=10'))
}
test()
first you need to parse the response into json if it's a json API.
function fastapiRequest(path) {
return fetch(`${path}`)
.then((response) => {
return response.json();
});
}
you need to 'await' for the rsponse
you need to write the below code in an async function
const xxxx = await fastapiRequest(
`http://0.0.0.0:8008/xcascasc/Dexaa/Emo.json?Magic=Dexxaa&emotion=expressions`
);
When you make an http request using fetch in javascript it will return a Promise, it's not stuck it's just need to be resloved, you can resolve it just like the above code with async await, or you can use the .then(() => { /* code... */ }) function, you can also use .catch(() => { /* handle error... */ }) function to handle errors.
In Your curl you use x_token as header variable, if it's required you need to pass a header with your path too. All other answers are valid too.

Node/Typescript Async/Await [duplicate]

This question already has answers here:
Why do I need to await an async function when it is not supposedly returning a Promise?
(3 answers)
Closed 11 months ago.
I am trying to get an auth token from an API and then store that Auth token and use it in subsequent calls to the API.
This is the code to get the token
const getToken = async (): Promise<string | void> => {
const response = await fetch('https://exampleapi.com/auth', {
method: 'POST',
body: JSON.stringify(body),
headers: headers,
agent: httpsAgent
})
const data = await response.text().then(txt => {
const cred = xml2json(txt);
const cred2: authResponse = JSON.parse(cred);
const tkn = cred2.elements[0].elements[0].attributes.token;
return tkn;
}).catch(err => console.log(err));
return data;
}
However it is returning a promise even though I am .then() and .catch() -ing.
If I put a console.log() within the .then(), I am able to see the token that I want. However I'm not able to return it as a value so that it can be stored.
const tkn = getToken().then(data => console.log(data)).catch(err => console.log(err));
I want the value of the token to be returned, not just to be able to console.log() the value I'm looking for. All the examples I am seeing are simply showing that I can console.log() the value I am looking for within the .then(), however that is not what I am trying to do. Sorry if this is not worded correctly would be happy to update with any relevant information needed. Would like to avoid top level await if possible.
You seem to be mixing await and .then() / .catch(). Change the second async request to:
try {
const text = await response.text();
const cred = xml2json(txt);
const cred2: authResponse = JSON.parse(cred);
const data = cred2.elements[0].elements[0].attributes.token;
return data;
} catch(error) {
console.log(err);
}

Issue regarding async functions - await is only valid in async functions [duplicate]

This question already has answers here:
await is only valid in async function
(14 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
In a file called getData.js , I wrote the following code
module.exports = async function (page, id) {
const options = {
...
};
axios
.request(options)
.then((response) => {
myData = JSON.stringify(response.data);
return myData;
})
.catch((error) => {
console.error(error);
});
};
Now in my main index.js file, I imported the above module then I have this snippet,
const server = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
let finalData = await getData(myPage, myID);
res.end(finalData);
});
When I run this node crashes and I get this error
SyntaxError: await is only valid in async functions and the top level bodies of modules
How do I make my code to work? I thought of using async-await becuase response.data is very big, but clearly I don't understand async-await functions fully. In the external module, If I try to return myData outside the .then block and also don't use async-await, then I get undefined finalData.

NodeJS Promises returning Pending [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
Context: I am trying to set up testing using jest and supertest for a MongoDB application I am writing
The aim: Assign a value returned from the postArticleByAPI function to a constant id.
Issue: It's returning Promise { <pending> }
What I have tried:
Promise.resolve(postArticleByAPI) results in the same issue.
Chaining a .then((res) => {console.log(res}) results in undefined.
I think I fundamentally don't understand promises, or namely how to assign values they return outside of the promise. Is this possible? Anyone have any tips?
const articleData = {title: 'Hello123', doi: '123', journal: 'Facebook'};
/**
* Posts an article through the API
* #param {Object} article - the article objection containing dummy data
* #return {string} request - the article id stored in the database
**/
async function postArticleByAPI(article) {
await request(app)
.post('/api/articles')
.send(article)
.expect(200)
.then((response) => {
expect(response.body.title).toBe(article.title);
expect(response.body.doi).toBe(article.doi);
expect(response.body.journal).toBe(article.journal);
expect(response.body.id).toBeTruthy();
return response.body.id;
});
}
describe('Test POST through API', () => {
test('It should response the POST method /api/articles', () => {
const id = postArticleByAPI(articleData);
console.log(id);
});
});
Indeed postArticleByAPI returns a Promise and it's not resolved at the time you log it. You should write this instead:
describe('Test POST through API', () => {
test('It should response the POST method /api/articles', async () => {
const id = await postArticleByAPI(articleData);
console.log(id);
});
});
Also don't forget to return the Promise from postArticleByAPI:
function postArticleByAPI(article) {
return request(app)
.post('/api/articles')
.send(article)
.expect(200)
.then((response) => {
expect(response.body.title).toBe(article.title);
expect(response.body.doi).toBe(article.doi);
expect(response.body.journal).toBe(article.journal);
expect(response.body.id).toBeTruthy();
return response.body.id;
});
}
If you want to use async and await, you should not use .then -
async function postArticleByAPI(article) {
const response =
await request(app)
.post('/api/articles')
.send(article)
.expect(200)
expect(response.body.title).toBe(article.title);
expect(response.body.doi).toBe(article.doi);
expect(response.body.journal).toBe(article.journal);
expect(response.body.id).toBeTruthy();
return response.body.id;
}

Node.JS recursive promise not resolving

i'm working with an API that allows me to sync data to a local DB. There is a syncReady API that I'm calling recursively until the sync batch is ready to start sending data. The recursion is working correctly and the .then callback is called, but the resolve function never resolves the response.
const request = require('request-promise');
const config = require('../Configs/config.json');
function Sync(){}
Sync.prototype.syncReady = function (token, batchID) {
return new Promise((res, rej) => {
config.headers.Get.authorization = `bearer ${token}`;
config.properties.SyncPrep.id = batchID;
request({url: config.url.SyncReady, method: config.Method.Get, headers: config.headers.Get, qs: config.properties.SyncPrep})
.then((response) => {
console.log(`The Response: ${response}`);
res(response);
}, (error) => {
console.log(error.statusCode);
if(error.statusCode === 497){
this.syncReady(token, batchID);
} else rej(error);
}
);
});
};
I get the 497 logged and the "The Response: {"pagesTotal";0}" response but the res(response) never sends the response down the chain. I've added a console.log message along the entire chain and none of the .then functions back down the chain are firing.
I hope I've explained this well enough :-). Any ideas why the promise isn't resolving?
Thanks!
First, you don't need to wrap something that returns a promise with a new Promise. Second, for your error case you don't resolve the promise if it is 497.
const request = require('request-promise');
const config = require('../Configs/config.json');
function Sync(){}
Sync.prototype.syncReady = function (token, batchID) {
config.headers.Get.authorization = `bearer ${token}`;
config.properties.SyncPrep.id = batchID;
return request({url: config.url.SyncReady, method: config.Method.Get, headers: config.headers.Get, qs: config.properties.SyncPrep})
.then((response) => {
console.log(`The Response: ${response}`);
return response;
})
.catch((error) => {
console.log(error.statusCode);
if(error.statusCode === 497){
return this.syncReady(token, batchID);
} else {
throw error;
}
})
);
};
Maybe something like the above will work for you instead. Maybe try the above instead. As a general rule of thumb, it's you almost always want to return a Promise.

Categories