Using fetch inside fetch is not executing all the fetch requests - javascript

I am trying to execute three fetch requests one by one. Each fetch request should trigger on completion of previous fetch request. Below is my code
const chopSegment = (token, frame_tag_url, tag_to_delete_id, chopped_tag_array, tags_for_index_update) => (dispatch) => {
let req = fetch(frame_tag_url + tag_to_delete_id + "/",
{
method: "DELETE",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
}
})
req.then(response => {
if (!response.ok) {
throw response;
}
else
return response.json();
}).then(response => {
return fetch(frame_tag_url,
{
method: "POST",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json",
},
body : JSON.stringify(tags_for_index_update)
}).then(response1 => {
if (!response1.ok) {
throw response1;
}
return response1.json();
}).then(response => {
for(let i = 0; i < chopped_tag_array.length; i++){
return fetch(frame_tag_url,
{
method: "POST",
body: JSON.stringify(chopped_tag_array[i]),
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
}
})
.then(response2 => {
if (!response2.ok) {
throw response2;
}
return response2.json();
}).then(response2 => {
dispatch(chopSegmentSuccess(response2))
}).catch(error => {
})
}
}).catch(error => {
})
}).catch(error => {
})
}
In my code, only first fetch i.e. "DELETE" gets executed? What am I doing wrong?

You can't do fetches in a loop. You're returning the first fetch that completes. Use promises or await/async to fetch in a loop.
How to return many Promises in a loop and wait for them all to do other stuff

I'd rather do it this way, Create an IIFE and call it recursively for the subsequent fetch request:
return dispatch =>{
var ctr = 0;
(function myFunc(url, headerObj){
fetch(url, headerObj)
.then(response => {
response.json().then(data=>{
ctr++;
if(ctr ===1 ){ // This could be any condition, say, something on the basis of response; I have taken `ctr` as a condition
myFunc(url, { //You may change this even to different URL, if needed
method: 'POST',
headers: {
'content-type': 'application/json',
'body': ...,
'Authorization':...
}
});
}else if(ctr === 2){
myFunc(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
'body': ...,
'Authorization':...
}
});
}else{
// Any other code
}
})
})
})(url, headerObj);
}

Related

Uncaught (in promise) TypeError: res.map is not a function

I'm trying to fetch a list of departments from an url in a react native application
import React,{ useState,useEffect} from 'react';
import { StyleSheet, LogBox,View,Text } from 'react-native';
export default function App() {
var [department,setDepartment]=useState([])
const token = /* my token here */
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
.then(response => response.json())
.then(data=>console.log(data)) // returns the correct data
.catch(error => console.error(error))
}
const getdepartment = async () => {
await getDepartments().then((res) => //here lays the problem
{res.map((p, key) => {
department.push({
name: p.name,
id: p.id,
});
});
});
};
useEffect(() => {
getdepartment();
}, []);
return (
<View>
<Text>
{department[0]}
</Text>
</View>
)
}
here res in the getdepartment() function is undefined despite the getDepartments() function returning correct data from the url
You are not returning a value from getDepartments, just a simple console.log.
You can convert the function in async/await:
const getDepartments = async () => {
const url = /*my api's url here*/
try {
const response = await fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
return await response.json();
} catch(e){
// error
}
}
or return a value from your function:
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
})
.then(response => response.json())
.catch(error => console.error(error))
}
If you are returning the result of the fetch then just return the result obtained from it, the issue is along with fetch, the response is also handled and the complete thing post to that is being returned which is not the result so you just need to skip this line .then(data=>console.log(data))
const getDepartments=()=>{
const url = /*my api's url here*/
return fetch(url, {
method: 'GET',
headers: { "Authorization": "Bearer" + token ,
'Accept': 'application/json',
'Content-Type':'application/json'
}
}).then(response => response.json()).catch(error =>
console.error(error))
}
// Here after fetching the result you can map the data
const getdepartment = async () => {
await getDepartments().then((res) =>
{res.map((p, key) => {
department.push({
name: p.name,
id: p.id,
});
});
});
};

Fetch inside map in react

I'm trying to fetch each campaign stats by its campaignId. campaignId is pulled from first api call and then while iterating i'm passing that id to next api call for each campaign stats. First api call gives the right result but while iterating and fetching it from second api call it throws and error of
Unhandled Rejection (TypeError): ids.map is not a function
export const loadStats = async () => {
const ids = await (await fetch('https://api.truepush.com/api/v1/listCampaign/1', {
method: "GET",
headers: {
Authorization: `${TOKEN}`,
"Content-Type": "application/json"
}
})).json()
const data = Promise.all(
ids.map(async (i) => await (await fetch(`https://api.truepush.com/api/v1/campaignStats/${i.data.campaignId}`, {
method: "GET",
headers: {
Authorization:`${TOKEN}`,
"Content-Type": "application/json"
}
})).json())
)
return data
};
I'm expecting all such stats while iterating:
https://i.stack.imgur.com/8kjwy.png
https://i.stack.imgur.com/VJni7.png (result of listCampaign/1)
Try this:
export const loadStats = async () => {
const ids = await (await fetch('https://api.truepush.com/api/v1/listCampaign/1', {
method: "GET",
headers: {
Authorization: `${TOKEN}`,
"Content-Type": "application/json"
}
})).json()
const data = Promise.all(
ids.data.map(async (i) => await (await fetch(`https://api.truepush.com/api/v1/campaignStats/${i.campaignId}`, {
method: "GET",
headers: {
Authorization:`${TOKEN}`,
"Content-Type": "application/json"
}
})).json())
)
return data
};

Async function unexpected behavior

At the moment I am working on an Electron app that is supplied with data via an API. The renderer calls a "backend function", which first gets the API key via Keytar and then executes the API call via axios.
The problem here is that Keytar always returns null/undefined, even if a similar function with the same functionality works without any problems, also because this point can only be reached if a valid API key is stored at all and this will also be queried by Keytar.
I am new to async/await-functions, maybe I didn't get something.
btw: Maybe the title doesn't fit too well, but I was a bit at a loss about this one.
(keytarService, username, baseUrl are globals)
Here is my code:
// Api-calling function
async function makeCall(method_type, url_path, data_array) {
keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}
//index_renderer.js
webContents.on('dom-ready', () => {
apiMain
.makeCall('GET', 'user/self')
.then((data) => {
console.log(data);
document.getElementById('username_text').innerText =
data.firstName + '' + data.lastName;
})
.catch((err) => console.log(err));
});
Similar function which is working:
async function isAuthenticated() {
apiKey = await keytar.getPassword(keytarService, username);
if (apiKey == null || apiKey == undefined) {
return false;
}
axios({
method: 'GET',
url: baseUrl + '/api/isAuthenticated',
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: {},
}).then(
(response) => {
console.log(response);
if (!response.data.authenticated) {
logout();
}
return response;
},
(error) => {
console.log(error);
logout();
return error;
}
);
}
// call of the working function in main.js
if (authProcess.isAuthenticated()) {
mainwin.loadFile('index.html');
} else {
mainwin.loadFile('login.html');
}
Thanks in advance.
You are missing important returns in MakeCall().
Try:
function makeCall(method_type, url_path, data_array) {
// return this promise to MakeCall
return keytar.getPassword(keytarService, username).then((apiKey) => {
if (apiKey == null || apiKey == undefined) {
return false;
}
// return this promise to keytar.getPassword then()
return axios({
method: method_type,
url: baseUrl + url_path,
headers: {
'content-type': 'application/json',
'X-AUTH-TOKEN': apiKey,
},
data: data_array,
}).then(
(response) => {
return response.data;
},
(error) => {
return false;
}
);
});
}

Javascript: Fetch DELETE and PUT requests

I have gotten outside of GET and POST methods with Fetch. But I couldn't find any good DELETE and PUT example.
So, I ask you for it. Could you give a good example of DELETE and PUT methods with fetch. And explain it a little bit.
Here is a fetch POST example. You can do the same for DELETE.
function createNewProfile(profile) {
const formData = new FormData();
formData.append('first_name', profile.firstName);
formData.append('last_name', profile.lastName);
formData.append('email', profile.email);
return fetch('http://example.com/api/v1/registration', {
method: 'POST',
body: formData
}).then(response => response.json())
}
createNewProfile(profile)
.then((json) => {
// handle success
})
.catch(error => error);
Ok, here is a fetch DELETE example too:
fetch('https://example.com/delete-item/' + id, {
method: 'DELETE',
})
.then(res => res.text()) // or res.json()
.then(res => console.log(res))
For put method we have:
const putMethod = {
method: 'PUT', // Method itself
headers: {
'Content-type': 'application/json; charset=UTF-8' // Indicates the content
},
body: JSON.stringify(someData) // We send data in JSON format
}
// make the HTTP put request using fetch api
fetch(url, putMethod)
.then(response => response.json())
.then(data => console.log(data)) // Manipulate the data retrieved back, if we want to do something with it
.catch(err => console.log(err)) // Do something with the error
Example for someData, we can have some input fields or whatever you need:
const someData = {
title: document.querySelector(TitleInput).value,
body: document.querySelector(BodyInput).value
}
And in our data base will have this in json format:
{
"posts": [
"id": 1,
"title": "Some Title", // what we typed in the title input field
"body": "Some Body", // what we typed in the body input field
]
}
For delete method we have:
const deleteMethod = {
method: 'DELETE', // Method itself
headers: {
'Content-type': 'application/json; charset=UTF-8' // Indicates the content
},
// No need to have body, because we don't send nothing to the server.
}
// Make the HTTP Delete call using fetch api
fetch(url, deleteMethod)
.then(response => response.json())
.then(data => console.log(data)) // Manipulate the data retrieved back, if we want to do something with it
.catch(err => console.log(err)) // Do something with the error
In the url we need to type the id of the of deletion: https://www.someapi/id
Just Simple Answer.
FETCH DELETE
function deleteData(item, url) {
return fetch(url + '/' + item, {
method: 'delete'
})
.then(response => response.json());
}
Here is good example of the CRUD operation using fetch API:
“A practical ES6 guide on how to perform HTTP requests using the Fetch API” by Dler Ari https://link.medium.com/4ZvwCordCW
Here is the sample code I tried for PATCH or PUT
function update(id, data){
fetch(apiUrl + "/" + id, {
method: 'PATCH',
body: JSON.stringify({
data
})
}).then((response) => {
response.json().then((response) => {
console.log(response);
})
}).catch(err => {
console.error(err)
})
For DELETE:
function remove(id){
fetch(apiUrl + "/" + id, {
method: 'DELETE'
}).then(() => {
console.log('removed');
}).catch(err => {
console.error(err)
});
For more info visit Using Fetch - Web APIs | MDN https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch > Fetch_API.
Some examples:
async function loadItems() {
try {
let response = await fetch(`https://url/${AppID}`);
let result = await response.json();
return result;
} catch (err) {
}
}
async function addItem(item) {
try {
let response = await fetch("https://url", {
method: "POST",
body: JSON.stringify({
AppId: appId,
Key: item,
Value: item,
someBoolean: false,
}),
headers: {
"Content-Type": "application/json",
},
});
let result = await response.json();
return result;
} catch (err) {
}
}
async function removeItem(id) {
try {
let response = await fetch(`https://url/${id}`, {
method: "DELETE",
});
} catch (err) {
}
}
async function updateItem(item) {
try {
let response = await fetch(`https://url/${item.id}`, {
method: "PUT",
body: JSON.stringify(todo),
headers: {
"Content-Type": "application/json",
},
});
} catch (err) {
}
}
Let me simplify this, you can straight up copy the code.
This is for PUT method :
fetch('https://reqres.in/api/users', + id {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'user'
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
and this is for DELETE :
fetch('https://reqres.in/api/users' + id, {
method: 'DELETE',
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
Note: I'm using dummy api here.
This is what worked for me when using the PUT method. This method allows me to effectively update the 1st item using my first name:
fetch('https://reqres.in/api/users', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 1,
first_name: 'Anthony'
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
Here are examples for Delete and Put for React & redux & ReduxThunk with Firebase:
Update (PUT):
export const updateProduct = (id, title, description, imageUrl) => {
await fetch(`https://FirebaseProjectName.firebaseio.com/products/${id}.json`, {
method: "PATCH",
header: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title,
description,
imageUrl,
}),
});
dispatch({
type: "UPDATE_PRODUCT",
pid: id,
productData: {
title,
description,
imageUrl,
},
});
};
};
Delete:
export const deleteProduct = (ProductId) => {
return async (dispatch) => {
await fetch(
`https://FirebaseProjectName.firebaseio.com/products/${ProductId}.json`,
{
method: "DELETE",
}
);
dispatch({
type: "DELETE_PRODUCT",
pid: ProductId,
});
};
};
const DeleteBtn = (id) => {
fetch(`http://localhost:8000/blogs/${id}`, {
method: "DELETE"
})
.then(() => {
navigate('/');
});
}
<button onClick={(event) => { DeleteBtn(blog.id)} }>delete</button>

How to get fetches in a Promise.all to await the result of another fetch statement that is conditional

I have a conditional fetch that determines a part of a URL for a subsequent fetch, but I only want it to run in certain conditions.
The following is not waiting and runs the try right away:
async function fetchURLs() {
let sessionWait = false;
if ((check1 === true) && (check2 === false))
{sessionWait = await getURL();
} else {sessionWait = true}
if (sessionWait === true){
try {
var [a, b, c] = await Promise.all([
fetch(dataUrl, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'post',
}).then((response) => response.text()).catch(error => console.log(error.message)),
fetch(settingsUrl).then((response) => response.text()).catch(error => console.log(error.message))
} catch (error) {
console.log(error);
}
});
}
async function getURL(){
let subDomain = 'a';
fetchAdd = "https://" + subDomain + ".dexcom.com/ShareWebServices/Services/General/LoginPublisherAccountByName"
await fetch(fetchAdd, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
}).then((res) => res.json()).then((SessionData) => dataUrl = "https://" + SessionData).catch(error => console.log(error.message));
return true;
}
const tasks = getTaskArray();
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain​.​then​(​chainResults =>
currentTask​.​then​(​currentResult =>
[ ...chainResults, currentResult ] )
);
}, Promise​.​resolve​([])).​then​(​arrayOfResults => {
// Do something with all results
});
This Link might help you.
https://decembersoft.com/posts/promises-in-serial-with-
array-reduce/

Categories