Fetch API Delay - javascript

I'm attempting to fetch data on my server using the fetch API for the request, but the request is taking FOREVER to process (it does eventually process). I'm using React as my view, and Express is serving up my pages. I've listed my Express and JSX code below. Any insight into why this may be happening (The 'mounted' message is logged immediately as expected, but the fetch API after delays) ?
Express:
app.use('/test',function(){
console.log('connected');
})
React.JS:
componentDidMount(){
console.log('mounted');
fetch('./test').then(function(response){
console.log(response);
}).catch(function(error){
console.log(error);
})
}

You have to send the response in the server side :
app.use('/test',function(request, response){
console.log('connected');
response.send(); //!!!!! this line
//Or: response.sendStatus(200); to send status code without body
});
... otherwise the endpoint will not be terminated.

Related

Implement JS back-end and provide it an existing React front-end as an `/api` URI

I've got an React app, which calls internally: /api/* actions. In my case these actions are satisfied by NginX which loads relevant back-end code and returns JSON response.
I would like this React app to be "self-served", I would like to implement API back-end: /api/* using JS, so the code runs in the browser.
My app uses: react-router
<BrowserRouter>
<Switch>
<Route path={"/users/:path*"} component={UsersPage} />
<Route path={"/api/:action*"} component={ApiComponent} /> // Return RAW Json here, is it possible?
<Route component={NotFoundPage} />
</Switch>
</BrowserRouter>
Is it possible somehow to resolve the /api/*, so I can implement it in my ApiComponent and return raw JSON?
I've also experimented with Express JS:
app.group("/api", (router) => {
router.get("/action", (req, res) => {
// Implement API action here
});
});
app.use('/public', express.static('public')) // This allows assets to be loaded from filesystem
app.get("*", (req, res) => {
res.sendfile('./index.html'); // This loads React app
});
which worked very well, but now I've ended up with a problem, how to run this Express JS / NodeJS, in a browser context.
In other words, my question is what are the ways to implement API on the front-end, provide to to existing React app, and run it all in browser.
If you are using an HTTP client library like Axios, you can use an interceptor, which is a function that gets called for every single HTTP request made and the response received by your application in the browser itself.
Here is the sample code,
// Add a request interceptor
axios.interceptors.request.use(function (request) {
// Do something before request is sent
request.headers.Authorization = 'Bearer <token>';
return request;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
if (response.status === 401) {
window.location = '/login';
}
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Another way is to register a service worker, which essentially acts as a proxy server and can intercept all HTTP requests.
Also, you can use browser extension like https://github.com/kzahel/web-server-chrome which creates a Web Server for Chrome, serves web pages from a local folder over the network, using HTTP. Runs offline.
It's impossible for React elements to return raw JSON because all React elements return a special object.
Maybe, you should just set a proxy in your webpack/vite config to point all /api requests to your node server.

Express node.js - Does the render function has a promise?

After rendering my index.html (which works fine), I would like to send some additional data via sockets. For that, I would need a promise for the rendering process. At the moment, the code runs synchron. The socket data is sent and moments later the data is overwritten due to the later ending rendering process. Looking for something like:
res.render('index', {title: "XYZ"})
.then(function(){
//.. do something
});
Is there a different approach? Or is the only solution to ask for the data via the client?
Thanks for any help!
Does the render function has a promise?
The documentation doesn't mention one, so presumably not.
For that, I would need a promise for the rendering process.
Not necessarily, just some kind of notification that the data had been sent. Promises are one kind of notification, but not the only kind.
The docmentation shows that render will call a callback function with the rendered HTML, so you could use that callback to send the HTML along with whatever you want to have follow it:
res.render("index", {title: "XYZ"}, function (err, html) {
if (err) {
// ...send an error response...
return;
}
res.send(html);
// ...send your other stuff here...
});
But if you want a promise, you could use util.promisify on res.render. It's a bit of a pain because promisify doesn't make handling this straightforward, so you have to use bind:
const resRender = util.promisify(res.render.bind(res));
// ...
resRender("index", {title: "XYZ"})
.then(html => {
res.send(html);
// ...send your other stuff here...
})
.catch(err => {
// ...send an error response...
});
You've said you're sending further information "via sockets." That makes it sound to me like the further information you're sending isn't being sent via the res response, but via a separate channel.
If so, and if you want to wait to send that until the response is sent, you can start your socket sending in response to the finish event on the response:
res.on("finish", () => {
// Send your socket message here
});
res.render("index", {title: "XYZ"});
(Remember that an Express Response object is an enhanced version of the Node.js ServerResponse object, which is what provides this event.)
But even then, all that means is that the data has been handed over to the OS for transmission to the client. From the documentation:
...this event is emitted when the last segment of the response headers and body have been handed off to the operating system for transmission over the network. It does not imply that the client has received anything yet.
I don't think you have anything beyond that to hook into.

Angular. Get server response in catchError

I am using standard http service to send requests to server.
Sometimes server returns data with 503 HTTP error.
http.post<...>(url, body).pipe(map(result => {
console.log(result);
return result;
}),
catchError(err => throwError(err)));
I fall into catchError every time server returns HTTP error code. What I want to do - is to access the whole HTTP response (that contains some useful data even if HTTP error is returned within response).
How can I do that?
Thank you in advance!
You can subscribe the request and catch the error like this:
this.http.post(url, body).subscribe(
data => {
console.log(data);
},
err => {
console.log(err); // err.error for example for specific attribute
});
I hope this is helpfull.

Sending Many POST requests simultaneously Nodejs

I am new to Nodejs so excuse me for any mistake .. :)
Let me explain what i am trying to do :
basically i am making a push notification service for my platform .. i will explain further..
I have two NodeJs servers (using express) :
SERVER 1 :
it gets everything needed from the database such as ( device registration , identifier ..) and should send to the second server.
SERVER 2 : This server Receives a JSON ( contains everything i need ) to create the FCM and APNS payload and then send to the convenient provider (FCM,APNS).
what i am using : i am using axios to send POST requests.
The issue : since the 1st server will be sending big amount of requests ( usually 5K or more -- it's dynamic) at the same time , axios cannot handle that , and I've tried many other alternatives to axios but faced the same thing.
My question : How can i send that amount of requests without any issues ?
PS: when i send few requests ( 100 or bit more) i face no errors ...
I hope everything is clear and i would really appreciate any help.
Code Example of the Request with Axios :
PS: it always falls in the "[Request Error] ..."
try
{
axios.post(endpoint,{sendPushRequest})
.then( response => {
console.log(response.data);
})
.catch( er => {
if (er.response) {
console.log("[Response Error] on sending to Dispatcher...");
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(er.response.data);
console.log(er.response.status);
console.log(er.response.headers);
} else if (er.request) {
console.log("[Request Error] on sending to Dispatcher...");
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
} else {
// Something happened in setting up the request that triggered an Error
console.log('[Error]', er.message);
}
console.log(er.config);
});
}
catch (e) {
console.log('[ Catch Error]', e);
}
Usually, for doing this kind of asynchronous stuff you should use any queuing service as if the second server gets busy which it might in case of handling such a huge number of rest APIs your user would miss the notification.
Your flow should be like:
SERVER 1: it gets everything needed from the database such as ( device registration, identifier ..) and should push/publish to any queuing service such as rabbitMQ/Google pubsub etc.
SERVER 2: Instead of having rest APIs, this server should pull messages from the queue recursively and then Receives a JSON ( contains everything I need ) to create the FCM and APNS payload and then send to the convenient provider (FCM, APNS).
This is beneficial because even if anything happens to your server like busy/crashes the message would persist in the queue and on restarting the server you would be able to do your work(sending a notification or whatever).

Client side unable to hit its own server endpoint

I've a AngularFullStack project in which I'm trying to hit my project's server endpoint using the following code, however the problem is the call isn't going through from angular client side to the nodejs server. Since it's my first project, I've little to no idea what might be going wrong that might be causing this weird conflict.
ClientSide:
$http({
method: 'POST',
url: '/api/soapAPIs/soapAPI',
data: request,
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response) {
console.log("response from server is: ", response);
})
.catch(function(error) {
console.log("error in calling server is: ", error);
});
I have installed CORS on server side and wrote the following code in app.js but still it doesn't work.
Server App.js
// Setup server
var app = express();
var cors = require('cors');
//add cors to do the cross site requests
app.use(cors());
Server Endpoint Code:
export function soapAPI(req, res) {
console.log("SERVER SIDE ", req.body);
res.status(statusCode).json({"status":"success"});
res.send();
}
Following are the problems:
If I try to hit nodejs endpoint like this /api/soapAPIs/soapAPI, the browser shows pending request and it never goes to the server.
When I add the full classified url for the endpoint like this http:localhost:9000/api/soapAPIs/soapAPI, it hits the endpoint but then the client never receives response from the server. I don't want to provide the full classified URL on the client side for obvious reasons.
How can I resolve this issue? Please let me know if you need any other code/information.
EDIT:
By using full classified path, the server endpoint gets hit but its response is never received by the client side. I get this error in browser:
Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"/api/things","headers":{"Accept":"application/json, text/plain, */*"}},"statusText":""}
Uncomment the following line:
/*mongoose.connect(config.mongo.uri, config.mongo.options);
mongoose.connection.on('error', function(err) {
console.error(`MongoDB connection error: ${err}`);
process.exit(-1); // eslint-disable-line no-process-exit
});
*/
Basically this is causing your controller to not return any response because your mongoose models are being referenced but the connection to mongo fails.

Categories

Resources