Hey I'm using promise to fetch 2 different API calls, that both return files with similar/matching data.
I'm trying to use one of the API calls to display a couple of numbers (balance of 2 wallets), which worked fine when there was only one API call, I was doing it like this:
const rewardWallet = data.result[0];
const rewardBalance = rewardWallet.balance;
So, data.result[0] was selecting result, and then the first array (0) and then the data from 'balance'. But now that there are 2 API calls, 'result' is under '0' and I can't figure out how to select the top level.
Link to results API returns
I added the second API call like this:
Promise.all([
fetch('https://api.bscscan.com/api?module=account&action=balancemulti&address=0xa3968Fba9D45D52b6b978f575934364ac2d5774c,0x121F0a592a25A52E8834C87005CbF4db000010Af&tag=latest&apikey=key'),
fetch('https://api.bscscan.com/api?module=account&action=tokenbalance&contractaddress=0x7b50c95f065dc48a0ecf8e5f992bf9bb9f4299c5&address=0x121F0a592a25A52E8834C87005CbF4db000010Af&tag=latest&apikey=key')
]).then(function (responses) {
return Promise.all(responses.map(function (response) {
return response.json();
}));
}).then(function (data) {
console.log(data);
}).catch(function (error) {
console.log(error);
});
Appreciate any help.
You can use Promise.all to ensure request are fired off and then work with the response after all promises have resolved. See below, I've added some mock functions that mock the API calls that will just return an object with an amount.
const fetchWalletOne = () => {
return new Promise((resolve) => {
resolve({ amount: 1 });
});
};
const fetchWalletTwo = () => {
return new Promise((resolve) => {
resolve({ amount: 5 });
});
};
async function getData() {
const [walletOne, walletTwo] = await Promise.all([
fetchWalletOne(),
fetchWalletTwo()
]);
console.log(walletOne, walletTwo);
console.log(walletOne.amount + walletTwo.amount);
}
getData();
Related
I have an API that returns some values and depend on that values I want to create an array and pass that array in resolve. It works when set a timeout for resolve, for example, I set 5000 sec within 5 sec it fetch the data, push array and resolve. But I don't want to set a timeout. Please see the comments for bertter understand. its an nodejs function.
const calculateTotal = (arr) => {
let clientHotspotsTotal = [];
return new Promise((resolve, reject) => {
arr.forEach((data) => {
axios.get(`enpoint/data?.address`)
.then((response) => {
if (response?.data) {
console.log('API SUCCESS');
const val = (response?.data?.data?.total * data?.percentage) / 100;
clientHotspotsTotal.push({
total: val,
});
} else {
reject('API failed!');
}
})
.catch((error) => {
throw new Error(error);
});
});
resolve(clientHotspotsTotal); /// it return empty [], cause no time set for wait
setTimeout(() => {
resolve(clientHotspotsTotal) // it doesn't return empty because in that time api fetch data
an push into array
}, 5000)
});
};
So my question is how can I wait for that API response for multiple requests as I run a for loop for multiple users.
You can simplify this a lot by using async / await and Promise.all. We can create an array of promises from the axios calls, then get the response data using Promise.all.
We then iterate through the responses, returning the result.
const calculateTotal = async (arr) => {
const responses = await Promise.all(arr.map(data => axios.get(`enpoint/${data?.address}`)));
const clientHotspotsTotal = responses.map((response, i) => {
return({ total: (response?.data?.data?.total * arr[i]?.percentage) / 100});
});
return clientHotspotsTotal;
};
async function testIt() {
let result = await calculateTotal([
{ address: 'someaddress', percentage: 0.50 },
{ address: 'someaddress', percentage: 0.75 }
]);
console.log(result);
}
testIt()
This code i am about to put here does not work in the respect that my graphQL server always receives an empty array back... i know this is because the call completes before the data is available.. i don't have much experience with promises so i am wondering how i can get it to work, i played with a bunch of different combinations to attempt to await the response so that i could just pass back an array of id's to the playground... the browsewr.on(end) part works fine and the proper data shows in the console? Anyone care to shed some light for me?
const browser = await lookbookIndex.browseAll();
let hits = [];
let returnArray = [];
browser.on('result', (content) => {
hits = hits.concat(content.hits);
});
browser.on('end', () => {
console.log('Finished!');
console.log('We got %d hits', hits.length);
returnArray = hits ? hits.map(a => a.objectID) : [];
});
browser.on('error', err => err);
return returnArray;
Async syntax automatically wraps everything to Promise instance.
But you also can return Promise instance manually. It accepts callback with resolve & reject arguments. And you can call resolve to resolve the promise:
async function search() {
const browser = await lookbookIndex.browseAll();
return new Promise((resolve, reject) => {
let hits = [];
browser.on('result', (content) => {
hits = hits.concat(content.hits);
});
browser.on('end', () => {
console.log('Finished!');
console.log('We got %d hits', hits.length);
resolve(hits ? hits.map(a => a.objectID) : [])
});
browser.on('error', err => reject(err));
})
}
And you can await the promise:
await new Promise(...)
Similar questions:
Return data from function
I have few api call requests which i am trying to create promises and then execute all using Promise.all but, its giving empty value instead of array. Below is my code.
function getUser(arrUser) {
var student = [];
return new Promise((resolve, reject) => {
if (arrUser.length > 0) {
var promises = arrUseridRequest.map(userRequeset => {
return getRequest(userRequeset).then(result => {
student.push(JSON.parse(result.body).result[0].Name);
console.log(student); //This is giving right details.
}).catch(error => {
reject(error);
});
});
Promise.all(promises).then(StuName => {
resolve(StuName.join());
})
}
});
}
and this is how i am trying to get the values at once:
getUser('123').then(student => {
console.log(Student) //Coming as empty
});
getRequest is my api call nodeJs request module. What's wrong in my code?
All your promises fulfill with the value undefined since you're just logging the student names, but not returning them from the then callback. As you seem to be doing only a single request, the array will be [undefined], which is joined into the empty string.
Also avoid the Promise constructor antipattern:
function getUsers(arrUser) {
const promises = arrUser.map(userId => {
return getRequest(userId).then(result => {
const students = JSON.parse(result.body).result;
return students[0].Name;
});
});
return Promise.all(promises);
}
getUsers(['123']).then(studentNames => {
console.log(studentNames);
console.log(studentNames.join());
}).catch(console.error);
In node.js i have a databaseMapper.js file, that uses the Ojai node MapR api. to extract data. So far i have it working with single documents, but since this is an async api, i have a bit of issues with querying multiple documents.
This is what i have so far:
function queryResultPromise(queryResult) {
//this should handle multiple promises
return new Promise((resolve, reject) => {
queryResult.on("data", resolve);
// ...presumably something here to hook an error event and call `reject`...
});
}
const getAllWithCondition = async (connectionString, tablename, condition) =>{
const connection = await ConnectionManager.getConnection(connectionString);
try {
const newStore = await connection.getStore(tablename);
const queryResult = await newStore.find(condition);
return await queryResultPromise(queryResult);
} finally {
connection.close();
}
}
here it will only return the first because queryResultPromise will resolve on the first document.. however the callback with "data" may occur multiple times, before the queryResult will end like this queryResult.on('end', () => connection.close())
i tried using something like Promise.all() to resolve all of them, but I'm not sure how i include the queryResult.on callback into this logic
This will work
const queryResultPromise = (queryResult) => {
return new Promise((resolve, reject) => {
let result = [];
queryResult.on('data', (data) => {
result.push(data)
});
queryResult.on('end', (data) => {
resolve(result);
});
queryResult.on('error', (err) => {
reject(err);
})
});
};
So I know this question is asked a lot, but I'm trying to retrieve a variable that is created within a promise. The examples I've seen on here involve calling .then and using the data there, however what I'm trying to do involves an async function--which i cant use within the .then block.
Here's my code. I'm using the Asana API To call out a lists of tasks that are due. It successfuly logs it. But I want to save the list value from the last block as a variable that I can use elsewhere.
const asana = require('asana');
const client = asana.Client.create().useAccessToken("xxx");
client.users.me()
.then(user => {
const userId = user.id;
// The user's "default" workspace is the first one in the list, though
// any user can have multiple workspaces so you can't always assume this
// is the one you want to work with.
const workspaceId = user.workspaces[0].id;
return client.tasks.findAll({
assignee: userId,
workspace: workspaceId,
completed_since: 'now',
opt_fields: 'id,name,assignee_status,completed'
});
})
.then(response => {
// There may be more pages of data, we could stream or return a promise
// to request those here - for now, let's just return the first page
// of items.
return response.data;
})
.filter(task => {
return task.assignee_status === 'today' ||
task.assignee_status === 'new';
})
.then(list => {
console.log (util.inspect(list, {
colors: true,
depth: null
}));
})
.catch(e => {
console.log(e);
});
If you're open to rewriting your .then()'s as async/await something like this could work for you:
const fetch = require('node-fetch');
async function doit() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const json = await response.json();
console.log(json);
}
doit();