how to use websocket like an api [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed last month.
Improve this question
I have websocket connection between client(browser) & server.
Problem is, sometimes I request a data through websocket.
But since websocket works like an event, I cannot manage my code efficiently.
I can send websocket message in a function but then I have to listen and handle it on the event listener.
Below is example.
const ws = new WebSocket("ws://whatever");
function handleClickBtn() {
ws.send('request something');
// cannot get response here
}
ws.onmessage = function (event) {
console.log(`response comes here: ${event.data}`);
}
It seems harder to maintain my code since you have to jump between request and response.
If I've used REST API, it would been easier with async/await syntax.
What kind of technique can be used here?

You'll need to think in async terms and indeed handle many potential in-flight requests at the same time. To be able to do this, you will need to be able to relate the incoming responses to requests you sent previously. For example, you could add random ids to your requests, and the response to it will contain the same id. E.g.:
Request:
[82512903521, "fetch-data", "param1", "param2"]
Response:
[82512903521, {"some": "returned", "data": ...}]
Then internally you keep a list of request ids you sent, together with an appropriate callback function which you'll trigger when the corresponding response returns. E.g. something like:
const requests = {};
function request(callback, ...params) {
const id = randomId();
ws.send([id, ...params])
requests[id] = callback;
}
ws.onmessage = function (event) {
const [id, data] = event.data;
requests[id](data);
}
There are existing protocols and libraries that implement this kind of this, for example WAMP.

Related

How to slow down a node/rabbitmq message/react [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
I have a simulated real time app. I send a csv file to rabbitmq. And rabbitmq sends back the queues. In my client app, ag grid cannot keep with the speed of the received messages. I am using websocket.
I wonder how can I control the speed of those messages, either in rabbitmq, node js, websocket in the server or client? I want to control the speed of each response, e.g. To send/receive every response every second, minute, etc.
Thanks in advance
The solution was to control the flow of the queues. Use prefetch to indicate how many queues you want to consume at each time, and add a set time to indicate how often
channel.prefetch(1);
channel.consume(
queue,
msg => {
if (msg !== null) {
if(msg) {
setTimeout(() => {
console.log(msg.content.toString());
sendQueuesToWebSocket(msg.content.toString());
channel.ack(msg);
}, 50)
}
} else {
console.log('Consumer cancelled by server');
}
},
{
noAck: false,
}
);

Wait for WebHID response to be ready [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
Improve this question
I'm sending data to the target device using device.sendReport(reportID, dataBuffer) of WebHID, but trying to read the response before it gets ready (i.e) the response takes time to be generated.
For now by setting timeout for 10ms, I'm able to get the response. Would like to know if there are any better solution for this.
You haven't said how the device provides the response but I assume that it is in the form of an input report. In that case the Promise returned by sendReport() isn't particularly interesting but instead you want to listen for an inputreport event that will be fired at the HIDDevice. If you want you can turn this into a Promise like this,
const response = new Promise((resolve) => {
device.addEventListener('inputreport', resolve, { once: true });
});
await device.sendReport(...your data...);
const { reportId, data } = await response;
Once the response is received it will be stored in data.
Note that this assumes that the device only generates input reports in response to a request. For a device with more complex communications you may want to have an inputreport event listener registered at all times and process input reports based on their report ID or other factors. HID does not support any backpressure so if you don't have an inputreport event listener registered when a report is sent by the device it will be discarded.
For this type of action you should use asynchronous code. When sending/receiving things to or from a server, this action is a 'Promise' which is asynchronous.
It'll look something like this (using the fetch api as an example):
With callbacks (which are optional)
myFunction = () => {
fetch('POST', data)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.warn(error);
});
}
With async/await. This is not recommended in most cases, as this assumes that the request will succeed.
myFunction = async () => {
const response = await fetch('POST', data);
console.log(response);
}

How to efficiently pull data out of a huge api with multiple pages [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am currently using an API to create a React Redux application. My problem is I am confused about how to efficiently use the data as the API has more than 14470 "pages" to navigate around. My main goal is to display certain items in the API based on key value pair. For example I would say I want to display a category in the API based on a certain key value pair such as "highestRating" and want to map through the API to find out the five items with the highestRating, how would I be able to do this efficiently?
What I have tried so far is looping to get the entire API available to me but then I get stuck with my current task at hand.
export const fetchHighestRating = () => async dispatch => {
let data = [];
let morePagesAvailable = true;
let currentPage = 0;
while (morePagesAvailable) {
currentPage++;
const response = await api.get(
`/api?page%5Blimit%5D=10&page%5Boffset%5D=${currentPage}`
);
data = [...data , response];
morePagesAvailable = currentPage < 17471;
}
dispatch({ type: FETCH_HIGHEST, payload: data });
};
This is not a javascript problem, it is database. You should run query directly in database to test response speed and decide what to do next, including:
Sharding
Indexing
Optimize config of DB
....
Any above required research in type of DB you are using, the current situation of DB so there is no exactly answer now!

What's the best way to check a list of 1 millions codes in Firebase/Cloud function? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am using Firebase with Cloud function to test the good value of a code in a million pre-generated stored in Firebase Realtime Database.
It will be used in a mobile application to verify if a user have buy the bundle in real life.
I found 2 working solutions. In the first, I put the code directly in the name of the property. In the second I put the code in the child property called "key"
In the second case, the key parameter is indexed.
I need a fast (log n complexity) access to get the response.
Do you know if any of my solutions will work for about 1 million entries and 100 calls by second on Firebase.
(I am not familiar with NoSQL.)
In my sample, the codes are "ABCD-0000-000X"
(do not take the property called "user" in consideration)
First Solution : Use the code value as parent
Cloud Function source code
exports.checkKey = functions.https.onRequest((req, res) => {
const code = req.query.code;
return admin.database().ref("Codes/" + code).once("value").then(snapshot => {
if (snapshot.val() === null) {
return res.send("Invalid Code");
}
const nb = snapshot.child("nb");
if (nb.val() > 4) {
return res.send("NO more code");
}
snapshot.ref.update({ "nb": nb.val() + 1 });
return res.send("OK");
});
Second Solution : Use the code in child
exports.getKey = functions.https.onRequest((req, res) => {
const code = req.query.code;
var ref = admin.database().ref("Codes");
ref.orderByChild("key").equalTo(code).on("child_added", function (snapshot) {
const nb = snapshot.child("nb");
if (nb.val() > 4) {
return res.send("NOK");
}
snapshot.child("nb").set(nb.val() + 1);
return res.send("OK");
}
});
Thanks for your help.
There is no way you're going to be able to query a list of one million items. So storing the keys as a property named key is not going to work.
But if you keep the keys as the key of each item, means you can access the item by its path. And that scales really well.
So I'd go with your first approach.
That said: it's hard to recommend anything specific without knowing all use-cases, which nobody (including typically the project creator at an early stage) is likely to know. So I'd also recommend simply learning a bit more about NoSQL data modeling, by reading NoSQL data modeling, watching Firebase for SQL developers, and by experimenting with various approaches before committing to any specific one.

Dealing with pagination in database with AngularJS [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm trying to get all data from a custom API (flask with PostgresSQL database) using '$http' service in my controller but the api and database is constructed with pagination which means that if I wan't to access data a need to create services like this:
/*FIRST PAGE*/
$http.get("/api/test", testData)
.success(...)
/*SECOND PAGE*/
$http.get("/api/test?page=2", testData)
.success(...)
This is obviously not good solution but it works ! So could you guide me how to deal with this situation better ? because i know that this api contains over 1 thousand pages...
Cheers !
This is decribed in the official documentation.
Angular's $http service supports config param (second param of .get) which supports params parameter and do all the concatentaion with proper encoding etc etc for you.
params – {Object.<string|Object>} – Map of strings or objects which
will be serialized with the paramSerializer and appended as GET
parameters.
So you can do
angular
.module('xxx')
.factory('getPagedData', function ($http) {
return function(page) {
return $http.get("/api/test", { params: { page: page } });
}
});
And use it like this:
function someController(getPagedData) {
getPagedData(2).then(...); // will do GET /api/test?page=2
}
Also note, the .success method is deprecated. It is even removed in Angular 1.6. Use .then instead.
You can simply just pass a variable every time you want to page to the next data set. So you would have:
$http.get("/api/test?page="+ pageNum, testData).success(..)
Hope this helps!
Try creating a service that uses promises to access the data and break apart the data the way you want:
function getTestData(testData) {
return $http.get("/api/test", testData)
.then(function(response){ //Promise is successful create an object to store the data
}, handleError);
function testError(response){//Handle any errors if the promise fails
return response;
}
}
While this seems like a logical solution...
/* SERVICE */
var baseUrl = "/api/test";
MyService.getTests = function(page, testData) {
var pageParams = "";
if (page > 1) {
pageParams = "?page="+page;
}
return $http.get(baseUrl+pageParams, testData).success().error();
}
...GET requests don't allow you to send any data. I'm not sure how you plan to send testData to a $http.get request. The second parameter of a GET request is the config object, which makes your service much simpler.
var baseUrl = "/api/test";
MyService.getTests = function(page, testData) {
return $http.get(baseUrl, {params: {page: page}) //becomes /api/test?page=1
.success()
.error();
}

Categories

Resources