JS Pass data between methods - javascript

I have two methods:
Gets a photo with an ID
Gets a collection of photos with an ID
I'm trying to get the response data to pass into the savePhoto() method so I'm able to trigger the download.
So far I've had no look, no matter what I try.
Any and all advice/feedback would be helpful.
Thank you.
Attempt 1
const unsplashAxios = require('./unsplashAxios');
const fs = require('fs');
const request = require('request');
class Unsplash {
constructor() {
this.unsplash = null;
}
getPhoto(id){
this.unsplash = unsplashAxios( `/photos/${id}`);
this.unsplash.then((response) => {
console.log(response.data)
}).catch((response) => {
console.log(response);
});
return this;
}
getCollection(id){
this.unsplash = unsplashAxios(`/collections/${id}/photos`);
this.unsplash.then((response) => {
console.log(response.data)
}).catch((response) => {
console.log(response);
});
return this;
}
savePhoto() {
// Get response data
// const imgUrl = data.urls.raw;
// const imgPath = `${data.id}.jpg`
request('https://images.unsplash.com/photo-1571111937090-4452a4af8755?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEwNjE4NH0').pipe(fs.createWriteStream('eyJhcHBfaWQiOjEwNjE4NH0.jpg'));
}
}
myUnsplash = new Unsplash();
myUnsplash.getPhoto('PgHc0Ka1E0A').savePhoto();
myUnsplash.getCollection('62890').savePhoto();
Attempt 2
const unsplashAxios = require('./unsplashAxios');
const fs = require('fs');
const request = require('request');
class Unsplash {
constructor() {
this.unsplash = null;
}
async getPhoto(id) {
try {
this.unsplash = await unsplashAxios(`/photos/${id}`)
const response = this.unsplash
savePhoto(response)
} catch (error) {
console.error(error)
}
return this;
}
async getCollection(id) {
try {
this.unsplash = await unsplashAxios(`/collections/${id}/photos`)
const response = this.unsplash
savePhoto(response)
} catch (error) {
console.error(error)
}
return this;
}
savePhoto(response) {
console.log(response)
// Get response data
// const imgUrl = data.urls.raw;
// const imgPath = `${data.id}.jpg`
//request('https://images.unsplash.com/photo-1571111937090-4452a4af8755?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEwNjE4NH0').pipe(fs.createWriteStream('eyJhcHBfaWQiOjEwNjE4NH0.jpg'));
}
}
myUnsplash = new Unsplash()
myUnsplash.getPhoto('PgHc0Ka1E0A')
myUnsplash.getCollection('62890')

Related

I want to use axios's return to global state ,but Promise { <pending> }

const Board = () => {
...
const {selected} = useSelector(state => state.board);
// In Redux reducer ->
// const initialState = {
// selected : {}
// }
const getOnePost = async (id) => {
try {
const response = await axios.get(`/api/v1/post/${id}`);
const getOnePostData = await response.data;
selected = getOnePostData //I want to use Redux to use global state...
console.log(selected) //TypeError... and How to use global state..?
} catch(error) {
alert(error.response.data.message);
return Promise.reject(error)
}
}
const postClickHandler = (postId) =>
{
if(postId) {
// dispatch(boardSelected(postId));
getOnePost(postId)
}
}
...
}
This code uses axios.get to receive post information.
and I want to use api's return to global state(Redux state).
const getOnePost = async (id) => {
try {
const response = await axios.get(`/api/v1/post/${id}`);
const getOnePostData = await response.data;
return getOnePostData //return data
} catch(error) {
alert(error.response.data.message);
return Promise.reject(error)
}
}
const postClickHandler = (postId) =>
{
if(postId) {
getOnePost(postId).then((response)=>{
return{...selected, selected: response} //But Seleted: {}
})
}
}
Axios is a Promised-based JavaScript library that is used to send HTTP requests,
you have to get the promise result in the then method .
try this
const Board = () => {
...
const {selected} = useSelector(state => state.board);
// In Redux reducer ->
// const initialState = {
// selected : {}
// }
const getOnePost = async (id) => {
try {
const response = await axios.get(`/api/v1/post/${id}`);
response.then(function (rec) {
selected = rec.data //
//here update you state
console.log(selected)
}).catch(function (error) {
console.log(error);
});
} catch(error) {
alert(error.response.data.message);
return Promise.reject(error)
}
}
const postClickHandler = (postId) =>
{
if(postId) {
// dispatch(boardSelected(postId));
getOnePost(postId)
}
}
...
}
You can handle promise by using .then()
Try to initialize selected like below :
const response = await axios.get(`/api/v1/post/${id}`).then( response => {
selected = response
})
I don't know what kind of data is it. So, try to log response data, and use it.

How to improve the efficiency of an algorithm that does multiple fetch calls in terms of security and complexity?

The exercise is Write a JavaScript package that is able to:
fetch an array of URLs which contain JSON data
return their contents in a promise
I have already made a solution to this exercise, but I would like some input on how to improve this solution in terms of efficiency, security and complexity. I have also included unit tests for this solution.
index.js
const { InvalidParameterError, EmptyArrayError, InvalidURLError, FetchError, APIError } = require("./errors");
const fetch = require('node-fetch');
const validUrl = require('valid-url');
const links = [
'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/ftse-fsi.json',
'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-hkd.json',
'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-usd.json'
]
/**
* iterates through the array and fetches data from each url, includes edge cases
* #params {urls} array of URLs
* #return {Promise} promise which is an array of the data fetched from the URL in JSON format
*/
function requestMultipleUrls (urls) {
if (!Array.isArray(urls)){
console.log('Parameter passed is not in array format', urls)
return new InvalidParameterError('urls should be inside in an array')
}
if (urls.length === 0) {
console.log('Array cannot be empty', urls)
return new EmptyArrayError('Array of urls cannot be empty')
}
const promises = urls.map(async (url) => {
if ((!validUrl.isUri(url))) {
console.log('URL is in incorrect format', url)
return new InvalidURLError('Input URL is not in the correct format')
}
try {
const data = await fetch(url);
const { status } = data
if (status !== 200) {
console.log(`Your fetch call returned a status code of ${status}, check if the URL you entered is correct`)
return new APIError('Something went wrong with the URL you are trying to fetch', status)
} else {
return mapData(data)
}
} catch(error) {
console.log(error)
return new FetchError('Something went wrong during the fetch call')
}
})
return Promise.all(promises)
}
/**
* Deconstructs the data being passed to form an object that is eventually returned
* #params {data} response that is recieved from the fetch call in requestMultipleUrls
* #return {final} object that is formatted
*/
const mapData = async (data) => {
const {url, status} = data
const final = {
url,
status,
body: await data.json()
}
return final
}
requestMultipleUrls(links).then((data) => console.log(data))
module.exports = {
requestMultipleUrls
}
errors.js
class InvalidParameterError {
constructor (message) {
this.status = 400;
this.message = message;
}
}
class EmptyArrayError {
constructor(message) {
this.status = 400;
this.message = message;
}
}
class InvalidURLError {
constructor(message) {
this.status = 400;
this.message = message
}
}
class APIError {
constructor(message, status){
this.status = status,
this.message = message
}
}
class FetchError {
constructor(message) {
this.status = 502;
ths.message = message
}
}
module.exports = {
InvalidParameterError,
EmptyArrayError,
InvalidURLError,
FetchError,
APIError
}
index.spec.js
const { expect } = require('chai');
const { requestMultipleUrls } = require('../index');
const gbpUsd = require('./gbp-usd.json');
const gbpHkd = require('./gbp-hkd.json')
describe('requestMultipleUrl intended functionality', () => {
it('function should return an accumulated API response', async () => {
const dummyUrls = [
'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-usd.json',
'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-hkd.json'
]
const promise = await requestMultipleUrls(dummyUrls);
expect(promise).to.deep.equal([gbpUsd, gbpHkd]);
})
})
describe('requestMultipleUrl edge cases', () => {
it('should throw an error if the urls in the array do not match URI standards', async () => {
const dummyUrls = [
'lfkjklwfklm',
'ekefjkf;lfl;'
]
try {
await requestMultipleUrls(dummyUrls)
} catch (error) {
expect(error.message).to.eql('Input URL is not in the correct format')
}
})
it('should throw an error if URL array is empty', async () => {
const dummyUrls = []
try {
await requestMultipleUrls(dummyUrls)
} catch (error) {
expect(error.message).to.eql('Array of urls cannot be empty')
}
})
it('should throw an error if the parameter being passed is not an array', async () => {
const dummyUrls = 'https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-hkd.json'
try {
await requestMultipleUrls(dummyUrls)
} catch (error) {
expect(error.message).to.eql('urls should be inside in an array')
}
})
it('should throw an error if status code is not 200', async () => {
const dummyUrls = ['https://ft-tech-test-example.s3-eu-west-1.amazonaws.com/gbp-jpy.json']
try {
await requestMultipleUrls(dummyUrls)
} catch(error){
expect(error.message).to.eql('Something went wrong with the URL you are trying to fetch')
}
})
})

Why am I getting a network error on page refresh? (get request)

I'm making a get request to an API in a useEffect(). When I navigate to the page from the homepage it loads fine, but as soon as i refresh the page http://localhost:3000/coins/coin I get a Unhandled Runtime Error: Error: Network Error.
export async function getServerSideProps({ query }) {
const id = query;
return {
props: { data: id },
};
}
function index({ data }) {
const coinURL = data.id; // bitcoin
const apiEndpoint = `https://api.coingecko.com/api/v3/coins/${coinURL}`;
const [currentUser, setCurrentUser] = useState();
const [coinData, setCoinData] = useState([]);
useEffect(() => {
const getData = async () => {
const res = await axios.get(apiEndpoint);
const { data } = res;
setCoinData(data);
};
const getCurrentUser = async () => {
const res = await axios.get(
`http://localhost:5000/api/users/${session?.id}`
);
const { data } = res;
setCurrentUser(data);
};
getData();
getCurrentUser();
}, [coinData, currentUser]);
}
Why does this happen?
I'm recommending to do something like this:
const getData = async () => {
try {
const res = await axios.get(apiEndpoint);
const { data } = res;
setCoinData(data);
} catch(err) {
console.log(err)
}
};
const getCurrentUser = async () => {
try {
const res = await axios.get(
`http://localhost:5000/api/users/${session?.id}`
);
const { data } = res;
setCurrentUser(data);
} catch(err) {
console.log(err)
}
};
useEffect(() => {
getData();
getCurrentUser();
}, [coinData, currentUser]);
if you do so, you will be able to view the exact error and fix it.

nodejs javascript promise resolve

I can't seem to figure out how to save the results of SomeQuery promise. Essentially I would like to take the value in res and pipe it into parseQuery function and return the final results. How do I make the parsed result accessible to an APIs response.
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'xxx'
const password = 'xxx'
const someQuery = (query) => {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
tx.run(query)
.then((res) => {
// Everything is OK, the transaction will be committed
parseQuery(res)
})
.then(() => {
// Everything is OK, the transaction will be committed
})
.catch((e) => {
// The transaction will be rolled back, now handle the error.
console.log(e)
})
.finally(() => {
session.close()
driver.close()
})
}
const parseQuery = (result) => {
try {
const test = parser.parse(result)
console.log(test)
} catch (err) {
console.log(err)
}
}
module.exports = {
someQuery,
}
It finally clicked with me. Here is the solution I came up with. Hopefully it will help others. If there is a better way please let me know. Thank you #fbiville for you help.
async actions
const neo4j = require('neo4j-driver')
var parser = require('parse-neo4j')
const astria_queries = require('./astriaQueries')
const uri = 'bolt://astria_graph:7687'
const user = 'neo4j'
const password = 'neo'
async function getRecords(query) {
// run statement in a transaction
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session({ defaultAccessMode: neo4j.session.READ })
const tx = session.beginTransaction()
try {
const records = await tx.run(query)
const parseRecords = await parseQuery(records)
return parseRecords
} catch (error) {
console.log(error)
} finally {
session.close()
driver.close()
}
}
async function parseQuery(result) {
try {
const parsedRes = await parser.parse(result)
// console.log(parsedRes)
return parsedRes
} catch (err) {
console.log(err)
}
}
// getRecords(astria_queries.get_data_sources)
module.exports = {
getRecords,
}
api send()
exports.get_data_sources = async (req, res) => {
try {
queryFuns.getRecords(astria_queries.get_data_sources).then((response) => {
res.send(response)
})
} catch (error) {
res.status(500).send(error)
console.log(error)
}
}

response.text is not a function while building react-native app

I'm trying to build a react-native app with expo and while trying to sign up I get the following error message stemming from my api.js file:
response.text is not a function. (In 'response.text()', 'response.text' is undefined).
Here is my code:
const BASE_URL = "my local IP:5000";
export const api = async (url, method, body = null, headers = {}) => {
try {
const endPoint = BASE_URL.concat(url);
const reqBody = body ? JSON.stringify(body) : null;
const fetchParams = {method, headers};
if((method === "POST" || method === "PUT") && !reqBody) {
throw new Error("Request body required");
}
if(reqBody) {
fetchParams.headers["Content-type"] = "application/json";
fetchParams.body = reqBody;
}
const fetchPromise = fetch(endPoint, fetchParams);
const timeOutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("Request Timeout");
}, 3000);
});
const response = await Promise.race([fetchPromise, timeOutPromise]);
return response;
} catch (e) {
return e;
}
}
export const fetchApi = async (url, method, body, statusCode, token = null, loader = false)
=> {
try {
const headers = {}
const result = {
token: null,
success: false,
responseBody: null
};
if(token) {
headers["x-auth"] = token;
}
const response = await api(url, method, body, headers);
console.log(response);
if(response.status === statusCode) {
result.success = true;
if(response.headers.get("x-auth")) {
result.token = response.headers.get("x-auth");
}
Here is response.text()
let responseBody;
const responseText = await response.text();
//const responseText = await response.json();
try {
responseBody = JSON.parse(responseText);
} catch (e) {
responseBody = responseText;
}
result.responseBody = responseBody;
return result;
}
Here is response.text()
let errorBody;
const errorText = await response.text();
//const errorText = await response.json();
try {
errorBody = JSON.parse(errorText);
} catch (e) {
errorBody = errorText;
}
result.responseBody = errorBody;
console.log(result);
throw result;
} catch (error) {
return error;
}
}
Any help would be immensely appreciated.

Categories

Resources