How to clear request cache after attempting to multiple request in cypress? - javascript

Here is my code, I pass array of ids and for each ids I hit Api request.
for (let i = 0; i < 10; i++) {
cy.request({
method: 'GET',
url: `https://[API endpoint ]/api/v1/[requst]/${ids[i]}`,
headers: {
"authorization": token
}
})
.then((res) => {
return usernames.push([{ value: res.body.instagrams[0].username }])
})
.then((res) => {
return cy.wait(2000)
})
}
Whenever I execute the code, for 2-3 requests it works fine and then throws error like
Uncaught Error: invalid payload
I can see my URI is proper and sending correct request.

you should modify your code to wrap all the pending promises into an array. A modified snippet is as below:
async function processRequest(){
let result;
let promises = [];
for (let i = 0; i < 10; i++) {
promises.push(cy.request({
method: 'GET',
url: `https://[API endpoint ]/api/v1/[requst]/${ids[i]}`,
 headers: {
"authorization": token
}
}))
}
result = await Promise.all(promises);
for(let i = 0; i < 10; i++){
usernames.push([{ value: result[i].username }])
}
}

Here cy.request doesn't work properly with Promise.
Either while pushing it to promise array, remove cy.request() or purely handle with javascript.
async findUserName(ids, token) {
let promise = []
let usernames = []
ids.forEach(id => {
promise.push(
fetch(`https://[host]/api/v1/[endpoint]/${id}`, {
headers: {
'Content-Type': 'application/json',
"authorization": token
}
})
.then((res) => {
return res.json();
})
)
})
let result = await Promise.all(promise);
result.forEach((data) => {
usernames.push([{ value: data.instagrams[0].username }])
})
return usernames
}

Related

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);
})();

How to post Axios data has array inside?

I want to post files to groups. by storing the group id I want to send files to groupsFinal, but axios.post() will only post to the first array of groupsFinal, I tried for loop but it fails axios post.
let groups = [{id:"a001", groupName:"Group101"},{id:"a002", groupName:"Group202"}]
let groupsFinal = [];
for (let a = 0; a < groups.length; a++) {
let d = JSON.parse(JSON.stringify(groups[a]));
d.img = null;
groupsFinal.push(d);
}
let p = {
fileId: "file_001",
groups: groupsFinal, // array[]
};
return new Promise((resolve, reject) => {
axios
.post("/shareFileToGroup", p, {
headers: {
"Content-Type": "application/json"
},
})
.then(function (response) {
resolve("success");
})
.catch(function (error) {
reject("error");
})
.finally(function () {
// always executed
});
});

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);
}

How can I stop a loop from completing once it gets the first returned object from an API?

The code below receives all of the user's redeemed rewards from an API, I need to stop the loop from completing them all at once.
The for loop runs through all of the rewards the current user has redeemed through Twitch's API, then fulfills them if specific conditions are met. I want it to only fulfill one redemption, not all (x) amount of them.
The fulfill reward part happens at: fulfillReward()
For a full code snippet, click here: https://pastebin.com/7k5WNhmD
// looping over reward returned data
for (let i = 0; i < rewards.length; i++) {
async function fulfillReward() {
await fetch(
`https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${rewards[i].id}`,
{
method: 'PATCH',
headers: {
'client-Id': process.env.TWITCHBOT_CLIENT_ID,
Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 'FULFILLED',
}),
}
)
}
const currentReward = rewards[i]
const currentRewardUsername = currentReward.user_name.toLowerCase()
if (currentRewardUsername === input.toLowerCase()) {
countDocuments(discordID)
.then(() => {
return findOneUser(discordID)
})
.then(() => {
// All (x) amount of rewards get fulfilled instead of the first matching result
fulfillReward()
interaction.reply('success')
})
.catch((err) => console.log(err))
} else if (currentRewardUsername != input.toLowerCase()) {
return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
}
}
The general solution to exit a loop when a condition is met, is to incorporate a break statement in whatever conditional decides the loop has achieved its purpose early.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break
I've made a simple snippet that runs a million cycle for-next loop but terminates after 10 loops when a condition is met, using break.
let loopNumber = 0;
for (let i=0; i<1000000; i++)
{
loopNumber++;
if (loopNumber==10) {
break;
}
} // next i;
console.log(loopNumber);
Not sure I understood completely what you actually want but lets try:
async function fulfillReward(reward) {
await fetch(
`https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${reward.id}`,
{
method: 'PATCH',
headers: {
'client-Id': process.env.TWITCHBOT_CLIENT_ID,
Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 'FULFILLED',
}),
}
)
}
If you just receive the reward as a parameter you don't need to declare functions inside the for (please don't ever do that)
Then you call it sending the reward parameter
if (currentRewardUsername === input.toLowerCase()) {
countDocuments(discordID)
.then(() => {
return findOneUser(discordID)
})
.then(() => {
fulfillReward(currentReward)
interaction.reply('success')
})
.catch((err) => console.log(err))
} else if (currentRewardUsername != input.toLowerCase()) {
return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
}
I updated your code here https://pastebin.com/clone/7k5WNhmD, but cant really test it, so please let me know if you need something else
try this.
for (let i = 0; i < rewards.length; i++) {
async function fulfillReward() {
await fetch(
`https://api.twitch.tv/helix/channel_points/custom_rewards/redemptions?broadcaster_id=58606718&reward_id=08d5e2d9-ddd7-4082-bc78-39b06b35cd68&id=${rewards[i].id}`,
{
method: 'PATCH',
headers: {
'client-Id': process.env.TWITCHBOT_CLIENT_ID,
Authorization: `Bearer ${process.env.TWITCHBOT_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
status: 'FULFILLED',
}),
}
)
}
const currentReward = rewards[i]
const currentRewardUsername = currentReward.user_name.toLowerCase()
if (currentRewardUsername === input.toLowerCase()) {
function doSomething() {
return new Promise((resolve, reject) => {
countDocuments(discordID)
.then(() => {
return findOneUser(discordID)
})
.then(() => {
// All (x) amount of rewards get fulfilled instead of the first matching result
fulfillReward()
interaction.reply('success')
resolve(true);
})
.catch((err) => console.log(err))
})
}
const ret = await doSomething();
if (ret)
return ;
} else if (currentRewardUsername != input.toLowerCase()) {
return interaction.reply(`The Twitch user **${input}** has not redeemed the channel reward!`)
}
}

Promise.all() with dynamically sized array of requests using await

I'm new to JavaScript and Promises. I need to send an array of requests using Promise.all and await. Unfortunately, I do not know the size of the array, so it needs to be dynamic. The array would be requests. Ex:
let arrayOfApiCreateRecords = [];
arrayOfApiCreateRecords.push(apiCreateRecords(req, { clientHeaders: headers, record }));
let responses = await Promise.all( arrayOfApiCreateRecords );
I tried to write my code like this, but I seem to be stuck. Is it possible to rewrite the code using Promise.all and await with a dynamic array of requests? Please advise. Below is what I have:
'use strict';
const { apiCreateRecords } = require('../../../records/createRecords');
const createRecords = async (req, headers) => {
let body = [];
let status;
for(let i = 0; i < req.body.length; i++) {
let r = req.body[i];
let record = {
recordId: r.record_Id,
recordStatus: r.record_status,
};
const response = await apiCreateRecords(req, { clientHeaders: headers, record });
status = (status != undefined || status >= 300) ? status : response.status;
body.push(response.body);
};
return { status, body };
};
module.exports = {
createRecords,
};
Okay, I'm going to use fetch API to demonstrate the usage of Promise.all()
Normal usage (for one fetch call)
let user = { username: 'john.doe', password: 'secret' };
try{
let res = await fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
})
console.log('User creation response: ', res);
}
catch(err){
console.error('User creation error: ', err);
}
Now let's use Promise.all()
const users = [
{ username: 'john.doe', password: 'secret' },
{ username: 'jane.doe', password: 'i-love-my-secret' }
];
const requests = [];
// push first request into array
requests.push(
fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user[0])
})
);
// push second request into array
requests.push(
fetch('https://example.com/user/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user[1])
})
);
try{
const responses = await Promise.all(requests);
console.log('User creation responses: ', responses);
}
catch(err){
console.log('User creation error: ', err);
}

Categories

Resources