How to send multiple Images in a response? - javascript

I'm trying to get a list of all of my uploaded images (array of images) from a db using express. However, when I make a request to get them, I get a weird square, or I get a lot of weird characters.
I've tried streaming the array as a whole, I've tried sending it using res.end/res.write one by one by looping through the array, I've tried streaming and piping, but so far, nothing.
//gets data from db
let getAllPhotos = await ListingPhoto.find({
"listing._id": listingId
}).then((images) => {
return images.map(item => {
//want to send response here as we go
return item.file;
})
})
//or send all the files(images) that's in getAllphotos down here
I want to be able to see all of the photos in the response

Related

Fetching data from multiples pages of API

I'm fetching data from a PS4 Games API but it's split into 400+ pages. I wanted to get the data from all pages, but the solution I came up with did not work very well. It gives me an error 'JSON Value of type NSNull cannot be converted to a valid URL'. Also, I don't think the for loop works well either, it shows me it going through all the pages when it displays the results in my list.
Additionally, this API is dynamic because new games keep getting released. So how could I get data up to latest page without manually changing my last page number everytime? I looked at some questions here but I couldn't fit it into my code
My code is rather long so I'm just going to post the part that matter:
componentDidMount() {
var i;
for (i = 0; i < 400; i++) {
fetch(`https://api.rawg.io/api/games?page=${i+1}&platforms=18`, {
"method": "GET",
"headers": {
"x-rapidapi-host": "rawg-video-games-database.p.rapidapi.com",
"x-rapidapi-key": "495a18eab9msh50938d62f12fc40p1a3b83jsnac8ffeb4469f"
}
})
.then(res => res.json())
.then(json => {
const { results: games } = json;
this.setState({ games });
//setting the data in the games state
});
}
}
The API also has an item that gives me the link of the next page, I think there is a way to use 'next' and fetch data from that URL
If anyone could help, that would be AWESOME. Thank you in advance
its my first answer on this forum, so... I hope be helpfull.
For me you have 2 options:
Each request send 2 variables in the answer count and next, or you make a for loop with count/20 as limit (20 is the number of items gaves in the answer), or you make a while loop until the next variable give null as answer (currently at page 249).
What is currently happening is you are making 400 requests and when each comes in it is overwriting the component with the response it received. It does not care about what is already there or any of the other requests.
An approach you could try instead is as the responses come in append the results to the ongoing list and update the state with the running list.
Going forward and for your other question about handling new releases. Instead of running 400 queries every time the application is used, try looking into caching the results. When the app loads you can see if cache exists and load or query if it does not. The rawg.io /games endpoint has a parameter for ordering by release. When the application loads in future you can conditionally loop until you reach a game that is already in cache at which point terminate.

How to get data from back end side, to use it in the browser side?

I am new to programming, and I heard that some guys on this website are quite angry, but please don't be. I am creating one web app, that has a web page and also makes som ecalculations and works with database (NeDB). I have an index.js
const selects = document.getElementsByClassName("sel");
const arr = ["Yura", "Nairi", "Mher", "Hayko"];
for (let el in selects) {
for (let key in arr) {
selects[el].innerHTML += `<option>${arr[key]}</option>`;
}
}
I have a function which fills the select elements with data from an array.
In other file named: getData.js:
var Datastore = require("nedb");
var users = new Datastore({ filename: "players" });
users.loadDatabase();
const names = [];
users.find({}, function (err, doc) {
for (let key in doc) {
names.push(doc[key].name);
}
});
I have some code that gets data from db and puts it in array. And I need that data to use in the index.js mentioned above, but the problem is that I don't know how to tranfer the data from getData.js to index.js. I have tried module.exports but it is not working, the browser console says that it can't recognize require keyword, I also can't get data directly in index.js because the browse can't recognize the code related to database.
You need to provide a server, which is connected to the Database.
Browser -> Server -> DB
Browser -> Server: Server provides endpoints where the Browser(Client) can fetch data from. https://expressjs.com/en/starter/hello-world.html
Server -> DB: gets the Data out of the Database and can do whatever it want with it. In your case the Data should get provided to the Client.
TODOs
Step 1: set up a server. For example with express.js (google it)
Step 2: learn how to fetch Data from the Browser(Client) AJAX GET are the keywords to google.
Step 3: setup a Database connection from you Server and get your data
Step 4: Do whatever you want with your data.
At first I thought it is a simple method, but them I researched a little bit and realized that I didn't have enough information about how it really works. Now I solved the problem, using promises and templete engine ejs. Thank you all for your time. I appreciate your help)

how to maintain the order of http requests using node js?

I have a bunch of data that I want to send to a server through http. However in the server side I need to process the data in the same order as they were sent(e.g. if the order of sending is elem1, elem2 and elem3, I would like to process elem1 first, then elem2 and then elem3). Since in http, there is no grantee that the order will be maintained I need some way to maintain the order.
Currently I am keeping the data in a queue and I send one element and await for the response. Once the response reaches me I send the next element.
while (!queue.isEmpty()) {
let data = queue.dequeue();
await sendDataToServer(data);
}
I am not very sure if this will actually work in a production environment and what will be the impact on the performance.
Any sort of help is much appreciated. Thank you
Sorry, I don't have enough reputation to comment, thus I am posting this as an answer.
Firstly, your code will work as intended.
However, since the server has to receive them in order, the performance won't be good. If you can change the server, I suggest you implement it like this:
Add an ID to each data item.
Send all the data items, no need to ensure order.
Create a buffer on the server, the buffer will be able to contain all the data items.
The server receives the items and puts them into the buffer in the right position.
Example code:
Client (see Promise.all)
let i = 0;
let promises = [];
await sendDataLengthToServer(queue.length());
while (!queue.isEmpty()) {
let data = queue.dequeue();
data.id = i;
// no need to wait for a request to finish
promises.push(sendDataToServer(data));
}
await Promise.all(promises);
Server (pseudo-code)
length = receiveDataLengthFromClient()
buffer = new Array(length)
int received = 0
onDataReceivedFromClient(data, {
received = received + 1
buffer[data.id] = data
if (received == length) {
// the buffer contains the data in the right order
}
})

NodeJS + MySql nested queries

I'm trying to get users from database and then loop throug each user and get their images. However when I try to assign images array to user.images property nothing happens. I still get only users with empty images array.
Currently my code is the following:
user.getAll().then(result =>{
const userCollection = result[0];
for(let i=0; i < userCollection.length; i++){
userCollection[i].images = [{}];
image.getImagesByUserId(userCollection[i].Id).then(res =>{
userCollection[i].images = res[0];
}).catch(err =>{
console.log(err);
res.status(400).json(err);
})
}
res.json(userCollection);
})
.catch(err =>{
console.log(err);
res.status(400).json(err);
});
Why I can't assign images array to it's property?
It looks to me like you need to run your res.json(userCollection) from inside the callback.
This will of course mean you need to rename your res variable in the callback
This is assuming you are somehow using res.json(userCollection) to export the information. Which I am inferring based on the fact I don’t see res defined anywhere
May be a silly question, but are you assigning it? I only see
userCollection[i].images = [{}];
above and never see:
userCollection[i].images = res;
assignment once you grab the images.
The problem is that getImagesByUserId() is asynchronous so by the time you get to the assignment, you've already sent the response.
The order of events you have currently is:
Assign an empty image list to all the users
Queue up a load of database requests
Send the response (res.json())
Reassign the images for all the users once the database results come back.
The easy fix is to look at Promise.all() and aggregate the results when they all come back.
However, this isn't the most efficient way to deal with SQL databases, I would suggest you restructure your query so that you get all the images for all the users in 1 trip to the database and then format the response based on those results.
Say you have an image table and a user table, something like:
SELECT image_name, user_id
FROM image
then replace your loop in your js with:
getImagesForUsers().then(result => {
//create your response from the rows
res.json(response);
});

Soundcloud API: Can I specify my request?

I want to get a list of all tracks - resp. the IDs of those tracks - from a certain user. So I'm sending following request to the API (JavaSript SDK):
callPath = "/users/3817541/tracks";
SC.get(callPath,function(obj)
{
console.log(obj);
});
What I get back is an Array of Objects, each of them stuffed with all the track's detail out of which i can extract the IDs - but the transmission of all the unnecessary data slows down my application (I'm actually running this request for multiple users).
Is there any way to tell the API to return just a specific property (ID) of every object instead of the whole cake?

Categories