I have a mock server which serves some json data. The server works correctly, but how can I access the data via fetch/axios? I am using fetch to fetch from the endpoint http://localhost:6000/users.
const http = require('http');
const json = require('./users.json');
const port = 6000;
http.createServer((req, res) => {
if (req.url === '/users') {
// Test error
res.write(JSON.stringify(json)).end();
} else {
res.writeHead(404).end();
}
}).listen(port, () => console.log(`Mock server listening on port ${port}`))
const { data: usersData } = useFetch("http://localhost:6000/users")
Here is the hook
const [data, setData] = useState(null);
useEffect(() => {
const _fetch = async () => {
try {
const response = await fetch(url);
const json = await response.json();
setData(json);
} catch (err) {
console.log(err)
}
};
_fetch();
}, [url]);
return {
data,
};
};
export default useFetch;
I receive the below error message locally.
GET http://localhost:6000/users net::ERR_EMPTY_RESPONSE
useFetch.js?7d5b:38 TypeError: Failed to fetch
at _callee$ (useFetch.js?7d5b:22:1)
at tryCatch (runtime.js?96cf:63:1)
at Generator.invoke [as _invoke] (runtime.js?96cf:294:1)
at Generator.eval [as next] (runtime.js?96cf:119:1)
at asyncGeneratorStep (asyncToGenerator.js?dbc6:3:1)
at _next (asyncToGenerator.js?dbc6:25:1)
at eval (asyncToGenerator.js?dbc6:32:1)
at new Promise (<anonymous>)
at eval (asyncToGenerator.js?dbc6:21:1)
at _fetch (useFetch.js?7d5b:49:1)
```
const port = 6000;
useFetch("http://localhost:5500/users")
You're using two different port numbers, you should change one of them.
Related
I am retrieving a file from an S3 bucket and then forwarding it to another API. It's causing the following error:
DataCloneError: function httpAdapter(config) {
return new Promise(function dispatchHttpRequest(resolvePromise, rejectPromise)...<omitted>...
} could not be cloned.
at MessagePort.<anonymous> (file:///D:/Dev/beep/node_modules/serverless-offline/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js:24:10)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
The code used is here:
module.exports.fileUpload = async (event) => {
const bodyForm = JSON.parse(event.body);
const s3 = getS3Client();
const getObjectCommand = new GetObjectCommand({
Bucket: 'bucket-name',
Key: path.parse(bodyForm.name).name
});
const signedUrl = await getSignedUrl(s3, getObjectCommand);
const response = await axios.get(signedUrl, { responseType: 'stream' });
const form = new FormData();
form.append('file', response.data, bodyForm.edf_name);
await axios.post('https://api-url', form).then(res => {
console.log(res)
})
}
This issue happens (most probably) because your form object has methods in it (like your append method), and methods cannot be serialised.
You have two options here:
The hacky way, forcing a serializable form:
const serializableForm = JSON.parse(JSON.stringyfy(form));
await axios.post('https://api-url', serializableForm).then(res => {
console.log(res)
})
The better way, in which you map what form fields you need in your request
const serializableForm = {
foo: form.foo,
bar: form.bar
// ...
};
await axios.post('https://api-url', serializableForm).then(res => {
console.log(res)
})
I have the following files:
My routes - where the orders_count route lives:
routes/index.js
const express = require('express');
const router = express.Router();
const transactionsController = require('../controllers/transactionsController');
const ordersController = require('../controllers/ordersController');
const ordersCountController = require('../controllers/ordersCountController');
router.get('/transactions', transactionsController);
router.get('/orders', ordersController);
router.get('/orders_count', ordersCountController);
module.exports = router;
I then have my orders count controller living in the controllers directory:
controllers/ordersCountController.js
const ordersCountService = require('../services/ordersCountService');
const ordersCountController = (req, res) => {
ordersCountService((error, data) => {
if (error) {
return res.send({ error });
}
res.send({ data })
});
};
module.exports = ordersCountController;
My controller then calls my order count service which fetches data from another API.
services/ordersService.js
const fetch = require('node-fetch');
// connect to api and make initial call
const ordersCountService = (req, res) => {
const url = ...;
const settings = { method: 'Get'};
fetch(url, settings)
.then(res => {
if (res.ok) {
res.json().then((data) => {
return data;
});
} else {
throw 'Unable to retrieve data';
}
}).catch(error => {
console.log(error);
});
}
module.exports = ordersCountService;
I'm trying to return the JSON response. I initially had it setup with requests but looking at the NPM site, it appears that it's depreciated so have been digging through how to use node-fetch.
I have tried both 'return data' and res.send({data}), but neither are solving the problem.
I am still new to this so I am likely missing something very obvious, but how come I am not sending the JSON back through so that it displays at the /api/orders_count endpoint?
I keep thinking I messed something up in my controller but have been looking at it for so long and can't seem to figure it out.
Any help would be greatly appreciated and if there is anything I can add for clarity, please don't hesitate to ask.
Best.
please learn promises and await syntax. life will be easier.
never throw a string. always prefer a real error object, like that : throw new Error('xxx'); that way you will always get a stack. its way easier to debug.
avoid the callback hell : http://callbackhell.com/
you need to decide if you want to catch the error in the controller or in the service. no need to do in both.
in the controller you call the service that way :
ordersCountService((error, data) => {
but you declare it like that :
const ordersCountService = (req, res) => {
which is not compatible. it should look like this if you work with callback style :
const ordersCountService = (callback) => {
...
if (error) return callback(error)
...
callback(null, gooddata);
here is an example to flatten your ordersCountService function to await syntax, which allows the "return data" you were trying to do :
const fetch = require('node-fetch');
// connect to api and make initial call
const ordersCountService = async (req, res) => {
const url = ...;
const settings = { method: 'Get'};
try {
const res = await fetch(url, settings);
if (!res.ok) throw new Error('Unable to retrieve data');
return await res.json();
} catch(error) {
console.log(error);
}
}
module.exports = ordersCountService;
in fact i would prefer to error handle in the controller. then this woud be sufficient as a service
const fetch = require('node-fetch');
// connect to api and make initial call
const ordersCountService = async () => {
const url = ...;
const settings = { method: 'Get'};
const res = await fetch(url, settings);
if (!res.ok) throw new Error('Unable to retrieve data');
return await res.json();
}
module.exports = ordersCountService;
then you can call this funtion like this :
try {
const data = await ordersCountService(req, res);
} catch(err) {
console.log(err);
}
//or
ordersCountService(req, res).then((data) => console.log(data)).catch((err) => console.error(err));
I am trying to write a cloud function to export only the new documents getting added to my 'reviews' sub-collection. The trigger for this cloud function is: Cloud Firestore. However, my cloud function deployment fails through the console. Could someone please help me understand what's wrong with my cloud function?
Error message:
Deployment failure:
Build failed: /workspace/index.js:26
}
^
SyntaxError: missing ) after argument list
at new Script (vm.js:83:7)
at checkScriptSyntax (internal/bootstrap/node.js:620:5)
at startup (internal/bootstrap/node.js:280:11)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3); Error ID: d984e68f
Cloud function code:
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://bucket_name'
exports.scheduledFirestoreBackup = (event, context) => {
const databaseName = client.databasePath(
// process.env.GCLOUD_PROJECT,
"fs124",
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: ['reviews'],
})
.onSnapshot()
.then(snap => {
snap.forEach(doc => {
const response = doc.data();
console.log(doc.data());
return response;
}
});
Console snippet:
The message you are getting, SyntaxError: missing ) after argument list is pretty clear. You are missing the closing curly bracket} and parenthesis) of then(). It should look something like this:
const firestore = require('#google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();
const bucket = 'gs://bucket_name'
exports.scheduledFirestoreBackup = (event, context) => {
const databaseName = client.databasePath(
// process.env.GCLOUD_PROJECT,
"fs124",
'(default)'
);
return client
.exportDocuments({
name: databaseName,
outputUriPrefix: bucket,
collectionIds: ['reviews'],
})
.onSnapshot()
.then(snap => {
snap.forEach(doc => {
const response = doc.data();
console.log(doc.data());
return response;
});
});
};
Can I use axios and mongoose to build an API? That's because I am new in the back-end developement, so I tried and I gotta an error like below, I was trying to do an API with axios and mongoose, but I don't know if i can use them together, I was kind to test this code to see if they work, but apparently not. So any suggestion to code better or is that correct what I am doing, is there other way ? I sure there is, but which recommendion you guys can make.
I want to create two separate files, one for controllers like "product.controller" and use my api to do all the requests that my differents controllers could need
Error: socket hang up
at createHangUpError (_http_client.js:323:15)
at Socket.socketOnEnd (_http_client.js:426:23)
at Socket.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
product.controller.js
const Product = require('../models/product.model');
const api = require('../api/api');
mongoose = require('mongoose').set('debug', true);
// To create a new Product
exports.create = async (req, res) => {
const product = await api.create('/product', req.body);
res.status(201).send({ message: 'The product has been created successfully !', product });
};
api.js
const axios = require('axios');
const baseURL = require('../config/database');
const list = async(key) =>{
const content = await axios.get(baseURL.local.urlDataBase + key +'.json')
if(content.data){
const objects = Object
.keys(content.data)
.map(key=>{
return{
id: key,
...content.data[key]
}
})
return objects
}
return []
}
const get = async(key, id) => {
const content = await axios.get(`${baseURL.local.urlDataBase}/${key}/${id}.json`)
return {
id: id,
...content.data
}
}
const create = async(key, data) =>{
await axios.post(`${baseURL.local.urlDataBase}/${key}.json`, data)
return true
}
module.exports = {
list, create
}
Got this error while doing some react server side rendering with redux
Stack trace
TypeError: Cannot read property 'slice' of null
at dispatchHttpRequest (E:\Projects\real-estate\node_modules\axios\lib\adapters\http.js:84:37)
at httpAdapter (E:\Projects\real-estate\node_modules\axios\lib\adapters\http.js:19:10)
at dispatchRequest (E:\Projects\real-estate\node_modules\axios\lib\core\dispatchRequest.js:52:10)
at process._tickCallback (internal/process/next_tick.js:103:7)
Action
import axios from 'axios';
export const FETCH_USER = 'FETCH_USER';
export const FETCH_POSTS = 'FETCH_POSTS';
const GET_POSTS_URI = '/api/posts';
export const fetchPosts = () => {
let posts = axios.get(GET_POSTS_URI).catch(err => console.log(err));
return {
type: FETCH_POSTS,
payload: posts
}
}
API
app.get('/api/posts', function(req, res, next) {
Post.model.find()
.exec()
.then(function(posts) {
res.send(posts);
}, function(err) {
return next(err);
});
})
I still got the JSON response in the network tab in dev tool, but I could not retrieve the JSON response in the reducers. I also didn't get this error when I used OpenWeatherAPI
You are missing redux-thunk because you need it in order to do side-effect(like api call). Check out this: redux-thunk and redux async actions.