Wait for return value from function with async call in javascript [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 1 year ago.
I have a set of if-else conditions which calls a few functions and attribute properties to usr before redirecting this data to an external application.
if(funcA()) {
usr.a = funcA();
}
if(funcB()) {
funcB(user,context,function (error, ticket) {
usr.ticket = ticket;
});
}
redirect(usr);
funcB has two async API calls (using axios) and the script always trickles down to redirect before funcB returns a value.
function funcB(user, context, callback) {
let ticket = '';
const axios = require('axios#0.19.2');
const options = {method: 'POST', url: 'xxxx', data: '{xxxx}'};
axios(options).then(res => {
const access_token = res.data.access_token;
const options = {method: 'POST', url: 'xxx', data: `{xxxx}` };
axios(options).then(res => {
ticket = res.data.ticket;
callback(null, ticket);
}).catch(err);
}).catch(err);
}
I have tried using callback and async await but unsure how to wait for user.Ticket to be populated before redirect(usr) is called.

Making funcB return a promise should do the trick.
function funcB(user, context) {
return new Promise((resolve, reject) => {
const options = { method: "POST", url: "xxxx", data: "{xxxx}" };
axios(options)
.then((res) => {
const access_token = res.data.access_token;
const options = { method: "POST", url: "xxx", data: `{xxxx}` };
axios(options)
.then((res) => {
resolve(res.data.ticket);
})
.catch(reject);
})
.catch(reject);
});
}
Then use async await
if(funcB()) {
usr.ticket = await funcB(user,contex)
}
redirect(usr);
Edit: im assuming that the context where the if condition is running is already an async function if not you can do this
(async ()=>{
if(funcB()) {
usr.ticket = await funcB(user,contex)
}
redirect(usr);
})()

Related

Global variable is not updated [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed last month.
My test is querying a JSON and put value to 'text' variable,
but when trying to use the variable I'm getting an error:
cy.type() cannot accept an empty string. You need to actually type something
How can I use the text I got from the query?
here is the code:
var text = ''
const WebApiRequests = {
url : 'https://api.jsonbin.io/v3/b/62e129e3248d43754f074152',
makeRequest : function(method, url, body){
cy.request({
method: method,
url: url,
body: body
}).then((response) => {
text = response.body['record'][0]['team'];
});
}
}
const QueryingPage = {
inputNameObject : function(){
return cy.get('#inputName');
}
}
describe('Navigate to Querying page', () => {
it('Visits the Cypress website and clicks on the Querying menu', () => {
cy.visit('https://example.cypress.io/commands/querying');
WebApiRequests.makeRequest('GET', WebApiRequests.url, '');
QueryingPage.inputNameObject().type(text);
});
});
#Konrad is nearly correct, you need to return both the cy.request() and the result of the following .then().
But unfortunately you can't use async/await on Cypress commands as they do not return Promises, they return Chainer objects.
This is how you can adjust the code
const WebApiRequests = {
url: "https://api.jsonbin.io/v3/b/62e129e3248d43754f074152",
makeRequest: function (method, url, body) {
return cy // return the Chainable (it's not a promise)
.request({
method: method,
url: url,
body: body,
})
.then((response) => {
return response.body["record"][0]["team"]; // return the modified response
});
},
};
const QueryingPage = {
inputNameObject: function () {
return cy.get("#inputName");
},
};
describe("Navigate to Querying page", () => {
it("Visits the Cypress website and clicks on the Querying menu", () => {
cy.visit("https://example.cypress.io/commands/querying");
WebApiRequests.makeRequest("GET", WebApiRequests.url, "")
// use then to unwrap the Chainable
.then(text => {
QueryingPage.inputNameObject().type(text); // passes
})
});
});
This code should looks like this:
const WebApiRequests = {
url: "https://api.jsonbin.io/v3/b/62e129e3248d43754f074152",
makeRequest: function (method, url, body) {
// return the promise
return cy
.request({
method: method,
url: url,
body: body,
})
.then((response) => {
return response.body["record"][0]["team"];
});
},
};
const QueryingPage = {
inputNameObject: function () {
return cy.get("#inputName");
},
};
describe("Navigate to Querying page", () => {
// make the callback function async
it("Visits the Cypress website and clicks on the Querying menu", async () => {
cy.visit("https://example.cypress.io/commands/querying");
// await for the text
const text = await WebApiRequests.makeRequest(
"GET",
WebApiRequests.url,
""
);
QueryingPage.inputNameObject().type(text);
});
});

How to return the fetch from an async call [duplicate]

This question already has answers here:
async/await always returns promise
(4 answers)
Closed 2 months ago.
I'm really confused about asynchronous functions in general, but I can't seem to return what the api has fetched. Using console.log() gives all the results but I need the function's path (array) for later use.
function callRelation(id) {
(async () => {
const api = await fetch(
"https://www.overpass-api.de/api/interpreter?",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: "[out:json];rel(" + id + ");(._;>;);out;",
},
);
const request = await api.json();
let path = [];
for (let pair of request.elements){
if (pair.type === "node"){
path.push([pair.lat, pair.lon]);
}
}
console.log(path)
return path;
})();
}
let test = callRelation(10000);
console.log(test);
I've tried using something called a callback, but I failed miserably at that.
You await to get return from promise function.
async function callRelation(id) {
const api = await fetch("https://www.overpass-api.de/api/interpreter?", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: "[out:json];rel(" + id + ");(._;>;);out;",
});
const request = await api.json();
let path = [];
for (let pair of request.elements) {
if (pair.type === "node") {
path.push([pair.lat, pair.lon]);
}
}
console.log(path);
return path;
}
(async function () {
let test = await callRelation(10000);
console.log(test);
})();

Await is not as i expected in if else statements [duplicate]

This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 10 months ago.
let metadata = [];
allNFTs.map(async (e) => {
if (e.metadata) {
metadata.push(JSON.parse(e.metadata).attributes);
} else {
let config = {
method: "get",
url: `http://localhost:3000/api/fetch`,
header: {
"Content-Type": "application/json",
},
};
const res = await axios(config);
const attr = res.data.attributes;
metadata.push(attr);
console.log(metadata); // this one worked after below
}
});
console.log(metadata); // this one worked before above
But i want to wait till my axios done fetching, so i can finally console.log that my actual metadata.
Make an array of promises, and then await them with Promise.all
const metadataPromises = allNFTs.map((e) => {
if (e.metadata) {
return Promise.resolve(JSON.parse(e.metadata).attributes);
} else {
let config = {
method: "get",
url: `http://localhost:3000/api/fetch`,
header: {
"Content-Type": "application/json",
},
};
return axios(config).then((res) => res.data.attributes);
}
});
// await still has to be in an async function
const metadata = await Promise.all(metadataPromises);
console.log(metadata);
// or use .then
Promise.all(metadataPromises).then((metadata) => console.log(metadata));
The issue with you code, that you don't wait. The latest console.log is execurted before the map iterating all the items.
You should use somehting like that: https://www.npmjs.com/package/modern-async
E.g.
async function init() {
var ma= require('modern-async')
await ma.mapSeries(allNFTs,async (e)=>{
if (e.metadata) {
metadata.push(JSON.parse(e.metadata).attributes);
} else {
let config = {
method: "get",
url: `http://localhost:3000/api/fetch`,
header: {
"Content-Type": "application/json",
},
};
const res = await axios(config);
const attr = res.data.attributes;
metadata.push(attr);
console.log(metadata);
}
})
console.log(metadata);
}

JavaScript : Testing Promises with Timeout and conditions

I am trying to test my REST APIs using Mocha and Chai.
Below is code snippet
"use strict"
// all required varibles modules declaration
describe("Get Data", function () {
it("Get Final Data", function () {
return getFinalResponse(
"https://localhost/getdata",
"GET",
JSON.stringify(rawdata)
)
.then((response) => response)
.then(async (response) => {
console.log(response)
let jsonData = await response.json()
operationId = jsonData.operation
console.log(jsonData.operation)
})
})
})
function delay(t) {
return new Promise((resolve) => setTimeout(resolve, t))
}
async function restCall(url, method, data) {
const signer = new common.DefaultRequestSigner(provider)
const httpRequest = {
uri: url,
headers: new Headers(),
method: method,
body: data,
}
await signer.signHttpRequest(httpRequest)
const response = await fetch(
new Request(httpRequest.uri, {
method: httpRequest.method,
headers: httpRequest.headers,
body: httpRequest.body,
})
)
return response
}
async function getFinalResponse(url, method, data) {
let response
do {
await delay(10000)
response = await restCall(url + "/done", method, data)
} while ((await response.json()["status"]) !== "DONE")
return restCall(url, method)
}
The condition while(await response.json()["status"] !== 'DONE') breaks/terminates in 1 minutes but even after putting 2 minutes as mocha time out . I am not getting the expected output.
Kindly help me what might be the issue.

Promise object not returning a value

I am trying to get the value of asset:
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
console.log(asset);
The result is:
[object Promise]
How do I get the returned value from the request?
Using async and await is a practical way -
function axios(query) { // fake axios, for demo
return new Promise (r =>
setTimeout(r, 1000, { asset: query.params.assetId })
)
}
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
})
}
async function main() { // async
const asset = await getAssetInformation (11022) // await
console.log(asset)
}
main()
// 1 second later ...
// { asset: 11022 }
You will need to use .then function.
const asset = getAssetInformation(11002)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Promises return another promise.
The way to unpack and work with a promise is through the .then() function, which will run after the promise returns.
const asset = getAssetInformation(11002);
function getAssetInformation(id) {
return axios({
method: 'GET',
url: "/asset-information",
params: {assetId: id}
});
}
Asset here is a promise, you want to use a then on it to get the value.
Instead of..
const asset = getAssetInformation(11002);
use
getAssetInformation(11002)
.then((response) => {
//What you returned will be here, use response.data to get your data out.
} )
.catch((err) => {
//if there is an error returned, put behavior here.
})

Categories

Resources