JS read file onload returns undefined - javascript

I want to read a TXT file from a directory, I have this code which works fine
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
});
};
But I want to exe the fetch call in a function like so:
window.onload = () => {
const filePath = "file.txt";
const fileData = readDataFile(filePath);
console.log(fileData);
};
const readDataFile = path => {
fetch(path)
.then(res => res.text())
.then(data => {
return data;
});
};
But in this case, it returns undefined.
Another problem with it, is I can't catch if an error occurs, I tried adding catch to the promise and throw an error but it does not work. This is what I've tried:
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
})
.catch(err => {
throw new Error("ERROR!");
});
};
THANKS :)
This works:
const readDataFile = async path => {
try {
const response = await fetch(path);
const data = await response.text();
return data;
} catch (err) {
console.log('Cannot read file.');
}
}
window.onload = async () => {
const filePath = 'data.txt';
const fileData = await readDataFile(filePath);
console.log(fileData);
}
But again, the catch method does not work ? am I doing it wrong ?

Related

fetch api objects storing inside an array problems

I am fetching pokemon's name and image using a nested fetch method. I have successfully
created pokemon objects. but I am unable to store them inside pokemonsArray. what I am doing wrong here? how can I store them inside an array what should be a good approach to do it please guide me?
const cards = document.querySelector(".cards");
const error = document.querySelector(".err");
const search = document.querySelector("#search");
let url = "https://pokeapi.co/api/v2/pokemon?limit=100&offset=0";
let pokemonsArray = [];
const createPokemons = (pokemon) => {
pokemonsArray.push(pokemon);
};
const getPokemon = () => {
fetch(url)
.then((res) => {
if (!res.ok) {
throw new Error("data could not be fetched");
} else {
return res.json();
}
})
.then((data) => {
const pokemonArray = data.results;
pokemonArray.map((pokemon) => {
fetch(pokemon.url)
.then((result) => {
if (!result.ok) {
throw new Error("could not fetch new url");
} else {
return result.json();
}
})
.then((data) => {
let pokemon = {
name: data.species.name,
image: data.sprites.other.home.front_default,
};
createPokemons(pokemon);
});
});
})
.catch((err) => {
console.log(err);
});
};
console.log(pokemonsArray.length); // 0 !!! why result is 0;
getPokemon();

How to wait for the response from other call to create a request for post call

I have below 2 files, I want to make sure the call is in order. I tried the promise and callback, I have to admit, I am not 100% familiar with async calls.
config.js:
import rolesJson from '../../roles';
class Config{
url;
rolesList;
constructor(callback){
var baseurl = 'www.example.com/env';
fetch(baseurl)
.then(response => response.json())
.then(data => {
this.url = data.url;
getAuth(data.env);
}).catch((error) => {
});
const getAuth= (env) => {
const headers = { 'Content-Type': 'application/json' };
const options = { method: 'POST', headers, body:JSON.stringify(rolesJson(env))};
console.log("THIS BODY SHOULD NOT BE UNDEFINED", options.body);
fetch('www.example.com/auth', options)
.then(response => response.json())
.then(data => {
}).catch((error) => {
});
};
}
}
module.exports = Config;
roles.js
var roleUrl = 'www.example.com/roles';
const setEnviroment = (rolesdata,env) => {
let reqBody = {
"environment": env,
"components": rolesdata
}
console.log("REQUEST BODY CREATED", reqBody);
return req;
}
const getRoles = (env) => {
fetch(roleUrl)
.then(response => response.json())
.then(roles => {
let rolesList = [];
roles.map(x => {
const roleObj = {
name: x.name,
id: x.id,
}
rolesList.push(roleObj);
})
return setEnviroment(rolesList, env);
}).catch((error) => {
});
};
module.exports = getRoles;
How can I make sure when i am calling fetch('www.example.com/auth', options), the options.body is not undefined? I have tried to use async/await and callbacks, nothing works for me.
Any help will be very appreciated.
Thanks
No worries - promises are not easy to get at first. So first of all, you can only rely on the value, if you waited that it was resolved. This can be done, as you already pointed out, with .then or with async / await.
.then-solution:
var roleUrl = 'www.example.com/roles';
const setEnviroment = (rolesdata,env) => {
let reqBody = {
"environment": env,
"components": rolesdata
}
console.log("REQUEST BODY CREATED", reqBody);
return req;
}
const getRoles = (env) => {
fetch(roleUrl)
.then(response => response.json())
.then(roles => {
let rolesList = [];
roles.map(x => {
const roleObj = {
name: x.name,
id: x.id,
}
rolesList.push(roleObj);
})
return setEnviroment(rolesList, env);
});
// we return the promise
};
module.exports = getRoles;
class Config{
url;
rolesList;
constructor(callback){
var baseurl = 'www.example.com/env';
fetch(baseurl)
.then(response => response.json())
.then(data => {
this.url = data.url;
getAuth(data.env);
}).catch((error) => {
});
const getAuth= (env) => {
const headers = { 'Content-Type': 'application/json' };
const options = { method: 'POST', headers, body:JSON.stringify(rolesJson(env))};
console.log("THIS BODY SHOULD NOT BE UNDEFINED", options.body);
fetch('www.example.com/auth', options)
.then(response => response.json());
// we return the Promise
};
}
}
module.exports = Config;
// calling method
Config.getAuth(env).then((value) => {
return getRoles(env); //this returns a Promise again
}).then(x => {
// here you have the return type of getRoles
})
async-await-solution:
var roleUrl = 'www.example.com/roles';
const setEnviroment = (rolesdata,env) => {
let reqBody = {
"environment": env,
"components": rolesdata
}
console.log("REQUEST BODY CREATED", reqBody);
return req;
}
const getRoles = async (env) => {
let response await fetch(roleUrl); // awaiting fetch promise
let roles = await response.json(); // awaiting .json()-promise
let rolesList = [];
roles.map(x => {
const roleObj = {
name: x.name,
id: x.id,
}
rolesList.push(roleObj);
})
return setEnviroment(rolesList, env);
};
// async always returns a promise
module.exports = getRoles;
class Config{
url;
rolesList;
constructor(callback){
var baseurl = 'www.example.com/env';
fetch(baseurl)
.then(response => response.json())
.then(data => {
this.url = data.url;
getAuth(data.env);
}).catch((error) => {
});
const getAuth = async (env) => {
const headers = { 'Content-Type': 'application/json' };
const options = { method: 'POST', headers, body:JSON.stringify(rolesJson(env))};
console.log("THIS BODY SHOULD NOT BE UNDEFINED", options.body);
const response = await fetch('www.example.com/auth', options);
const body = await response.json();
return body; // we return a Promise including the body
};
}
}
module.exports = Config;
// calling method
const callerMethod = async () => {
const auth = await Config.getAuth(env);
const roles = await getRoles(env);
//now you can work with the resolved stuff
};
Please note, that callerMethod will return a Promise itself again, because it's async.

data output after receiving it in fetch

I apologize for the stupid question, please tell me how to transfer data from fetch (). then () to another function.
const http = require('http');
const https = require('https');
var urlZaprosHttp = 'http://ietf.org/';
var urlZaprosHttps = 'https://ietf.org/';
const fetch = url => new Promise((resolve, reject) => {
const protocol = url.startsWith('https') ? https : http;
protocol.get(url, res => {
if (res.statusCode !== 200) {
const { statusCode, statusMessage } = res;
reject(new Error(`Status Code: ${statusCode} ${statusMessage}`));
}
res.setEncoding('utf8');
const lines = [];
res.on('data', chunk => lines.push(chunk));
res.on('end', () => resolve(lines.join()));
});
});
// Usage
fetch(urlZaprosHttps)
.then(body => console.log(body))
.catch(err => console.error(err));
You can just simply call another function from within then() and do whatever you want with your data in that function:
fetch(urlZaprosHttps)
.then(body => someOtherFunction(body))
.catch(err => console.error(err));
const myFunc = (data) => {
console.log(data)
}
fetch(urlZaprosHttps)
.then(myFunc(data))
.catch(err => console.error(err));
In the then you can pass in a function and the data returned will be passed to that function, like in my example.

Promises resolving in wrong order

I am playing with promises and modified a script from Medium.
When I run the script it prompts for the code then displays the json data before I can input a value. I then input a value without the prompt for the script to exit.
How can I get the input before the API call works?
'use strict'
const request = require('request')
const readline = require('readline')
let userDetails
const getInput = prompt => new Promise( resolve => {
const io = { input: process.stdin, output: process.stdout }
const read = readline.createInterface(io)
read.question(`${prompt}: `, data => {
console.log(data)
read.close()
resolve(data)
})
})
const getData = () => new Promise( (resolve, reject) => {
const options = {
url: 'https://api.github.com/users/marktyers',
headers: {
'User-Agent': 'request'
}
}
// Do async job
request.get(options, (err, resp, body) => {
if (err) reject(err)
else resolve(JSON.parse(body))
})
})
function main() {
const GitHubAPICall = getData()
const getBase = getInput('input base currency')
GitHubAPICall
.then(result => {
userDetails = result
console.log('Initialized user details')
console.log(userDetails)
}).then(getBase)
.catch(err => console.log(err))
}
main()
In your main function, you can do it like that:
function main() {
const GitHubAPICall = getData; // WITHOUT ()
const getBase = getInput; // Those 2 declarations are useless, btw
GitHubAPICall()
.then(result => {
userDetails = result
console.log('Initialized user details')
console.log(userDetails)
})
.then(() => getBase())
.then(data => // Do something with the data returned by 'getInput')
.catch(err => console.log(err))
}

Refactoring how react/node handles response

I'm using a react frontend and fetching data from my node server. I feel like my code looks a bit redundant, is there a better way to refactor all this?
App.js
searchStock = async (value) => {
let priceURL = `/stock/${ value }/price`
// fetch price data
fetch(priceURL)
.then(res => {
if (res.ok) {
res.json()
.then( (result) => {
this.setState({
price: result
})
})
}
else {
console.log("Something went wrong...")
}
})
}
server.js
app.get('/stock/:symbol/price', (req, res) => {
const token = 'abcde123'
const symbol = req.params.symbol
const apiURL = `https://sandbox.iexapis.com/stable/stock/${symbol}/price?token=T${token}`
fetch(apiURL)
.then(response => {
console.log(response.status)
if (response.ok) {
response.json().then((data) => {
res.json(data)
});
}
else {
res.sendStatus(response.status)
}
})
.catch(error => {
console.log(error);
});
})
As these two code segments live in different apps (frontend and backend) I don't think there's a pretty way of DRYing this.
Introduce library file with fetching logic
src/helper.js
exports.fetchHelper = (url) => fetch(url)
.then(response => {
if (response.ok) {
return response.json();
} else {
res.sendStatus(response.status)
}
})
.catch(console.error);
and use respectively
app.js
import { fetchHelper } from 'src/helper'; // or whatever else your bundler setup requires
searchStock = async (value) => {
const priceURL = `/stock/${ value }/price`;
await fetchHelper(priceURL).then((result) => {
this.setState({
price: result
})
})
}
server.js
const fetchHelper = require('src/helper').fetchHelper;
app.get('/stock/:symbol/price', (req, res) => {
const token = 'abcde123'
const symbol = req.params.symbol
const apiURL = `https://sandbox.iexapis.com/stable/stock/${symbol}/price?token=T${token}`
fetchHelper(apiURL).then((response) => {
res.json(data);
})
Or something similar...

Categories