Why is no response being sent back in any of the cases (cache hit or miss)? I dont get any error either.
I'm trying to set up a simple redis based project.
import express from "express";
import axios from "axios";
let app = express();
import logger from "morgan";
import { createClient } from "redis";
const client = createClient();
await client.connect();
app.use(express.json());
app.use(logger("dev"));
app.get("/photos", async function (req, res) {
await client.get("photos", async (err, photos) => {
if (err) return next(err);
if (photos !== null) return res.json(JSON.parse(photos));
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/photos"
);
await client.setEx("photos", JSON.stringify(data));
res.json(data);
});
});
The issue is that you are mixing callback functionality with the newer async/await logic. According to the npm-redis docs the way to access a keys value is with await client.get()
app.get("/photos", async function (req, res) {
const photos = await client.get("photos");
if (photos) {
res.json(JSON.parse(photos))
} else {
try {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/photos"
);
await client.setEx("photos", JSON.stringify(data));
res.json(data);
} catch(error) {
console.error(error)
res.json({data: error})
}
}
});
I have also added a try/catch block around the call to axios.get to try and capture any error that comes from the call and return that error in the response
Related
I want to add data to my MongoDB collection. I'm getting this data via a local Flask API. I'm GETting the data on my React Frontend and it's displaying fine. I'm not sure why I can't do the same thing on my express nodejs backend. I want to get that same data and use it to build the entity that I'm going to store.
This is how I'm attempting to get the data
app.get('/', async (req, res) => {
let initialData = {};
axios.get('http://localhost:3000/details').then((res) => {
initialData = res.data;
});
const recruit = new RecruitModel({ email:initialData.email,
mobile_number:initialData.mobile_number,
name:initialData.name});
try {
await recruit.save()
res.send("inserted data")
} catch (error) {
console.log(error)
}
})
I'm pretty sure something wrong there and nowhere else. Because if I pass static information instead it's correctly stored, no issues.
You are saving to the database's Recruit Collection before the promise is resolved. Since data to save in the Recruit Collection is dependent upon the result from the API which will initially return the promise, therefore, use promise resolving functions to wait for its result.
Solution#1 (using .then function):
app.get('/', async (req, res) => {
let initialData = {};
try {
axios.get('http://localhost:3000/details').then((response) => {
initialData = response.data;
const recruit = new RecruitModel({
email: initialData.email,
mobile_number: initialData.mobile_number,
name: initialData.name,
});
recruit.save().then((response) => res.send('inserted data'));
});
} catch (error) {
console.log(error);
}
});
Solution#2 (using async await keywords):
app.get('/', async (req, res) => {
try {
const response = await axios.get('http://localhost:3000/details');
const recruit = new RecruitModel({
email: response.data.email,
mobile_number: response.data.mobile_number,
name: response.data.name,
});
await recruit.save();
res.send('inserted data');
} catch (error) {
console.log(error);
}
});
Either solution will work in your case.
I'm trying to create a basic caching app just to test redis. Im using Redis Version: 4.0.6.
First I was getting error clientclosederror: the client is closed.
Then, after reading the docs, I added
let client;
(async ()=> {
client = redis.createClient()
await client.connect()
})();
But now, when trying on Postman, it just hangs, no response is returned
Full Code:
const express = require("express");
const redis = require("redis");
const axios = require('axios')
const app = express();
let client;
(async ()=> {
client = redis.createClient()
await client.connect()
})();
app.get('/result', async (req, res) => {
const searchTerm = req.query.name;
try {
await client.get(searchTerm, async (err, result) => {
console.log('cached called')
if (err) throw err;
if (result) {
res.status(200).send({
result: JSON.parse(result),
message: "data retrieved from the cache"
});
}
else {
const result = await axios.get(`https://api.agify.io/?name=${searchTerm}`);
await client.set(searchTerm, JSON.stringify(result.data));
return res.status(200).send({
result: result.data,
message: "cache miss"
});
}
})
} catch (error) {
console.log('get error', error)
return res.status(500).send({ message: error.message })
}
})
app.listen(process.env.PORT || 3000, () => {
console.log("Node server started");
});
client.get doesn't need a callback function. It's async. My guess is that it's never getting called and thus Express is not returning anything.
Try this instead:
const result = await client.get('foo')
if (result !== null) {
// it's a hit
} else {
// it's a miss
}
I am learning unit testing. I wanted to mock the database response from the controller.
How can I do that?
here is my code:
imageController.ts
const getImages = async (req: Request, res: Response) => {
const images = await Image.find({}).sort({ date: -1 });
return res.status(200).json(images);
};
image.test.ts
describe("It shuld be get methoad", () => {
test("get all image url", async () => {
const res = await request(app).get("/api/v1/all");
expect(res.statusCode).toBe(200);
// console.log(res.body);
let images = res.body
// expect(images.length).toBeGreaterThan(0);
});
});
It seems you are using Mongoose, so I would suggest using a nice and quite popular library for mocking Mongoose: https://www.npmjs.com/package/mockingoose
I got a solution using the mongodb-memory-server package.
import request from "supertest";
import app from "../src/app";
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose from "mongoose";
import { fakeImage, fakeAddImage } from "../src/utils/data";
import Image from "../src/models/image";
describe("Image CRUD operation test", () => {
//For mocking db
beforeAll(async () => {
const mongoServer = await MongoMemoryServer.create();
await mongoose.connect(mongoServer.getUri());
});
afterAll(async () => {
await mongoose.disconnect();
await mongoose.connection.close();
});
it("should return a 200 & get image by id", async () => {
const image = await Image.create(fakeImage);
console.log("image", image);
const { body, statusCode } = await request(app).get(
`/api/v1/image/${image._id}`
);
// console.log("body", body);
expect(statusCode).toBe(200);
expect(body.data.title).toBe(image.title);
});
});
I'm working on building an inventory management application using PERN stack. I have a modal where I need to make 2 GET requests and when I console.log in front end both requests are getting Status 200 response. However in my express server, first get request is working fine but the second request is not receiving anything.
My frontend code
const openModal = async () => {
setDetailModalOpen(true)
try {
await Promise.all([
(async () => {
const serial_number = props.bacsSerial
const response = await fetch(`http://localhost:5000/bacslist/demoinventory/${serial_number}`)
const parseResponse = await response.json()
console.log(response)
setInputs({
bacsUnit: parseResponse.bacs_unit,
serialNumber: parseResponse.serial_number,
partNumber: parseResponse.part_number,
bacsLocation: parseResponse.bacs_location,
description: parseResponse.bacs_description
})
setBacsId(parseResponse.id)
setBacsData(parseResponse)
})(),
(async () => {
const response2 = await fetch(`http://localhost:5000/bacslist/demoinventory/${bacsId}`)
console.log(response2)
})()
])
} catch (err) {
console.error(err.message)
}
}
My backend code
router.get("/demoinventory/:serial_number", async (req, res) => {
console.log('This one is working')
try {
const {serial_number} = req.params
const getDemoBacs = await pool.query(
"SELECT * FROM demo_inventory WHERE serial_number = $1", [serial_number]
)
res.json(getDemoBacs.rows[0])
} catch (err) {
console.error(err.message)
}
})
router.get("/demoinventory/:bacsId", async (req, res) => {
console.log(req.params)
console.log('This one is not working')
try {
const getHistoryData = await pool.query(
"SELECT * FROM demo_inventory_history"
)
console.log(getHistoryData)
res.json(getHistoryData)
} catch (err) {
console.error(err.message)
}
})
Sorry, Kinda new to this stuff so this isn't exactly an answer but I'm not allowed to leave a comment. I can't see your state variables with the code you posted, but are you sure that BacsId is being set to state before it is used in the second call, or is the parameter in the second call being sent empty, thus not using the right URL? Just a thought.
I'm trying to implement Redis inside my NodeJS API but having issues to do so.
What I try is to make Redis for the endpoint which serves all the users as a response.
I'm getting this error from my implementationnode_redis:
The GET command contains a invalid argument type of \"undefined\".\nOnly strings, dates and buffers are accepted. Please update your code to use valid argument types.:
I tried in this way from connection to middleware:
import redis from 'redis';
import { redisConfig } from '../config';
import Logger from './logger';
// Redis default port === 6379
const REDIS_PORT = redisConfig.port || 6379;
// Connect to redis
const client = redis.createClient(REDIS_PORT);
// Check connection
client.on('connect', () => {
Logger.info('Connected to Redis');
});
client.on('error', () => {
Logger.error('Redis not connected');
});
export default client;
Then using this above in my controller:
import Client from '../loaders/redis';
const UserController = {
async getAllUsers(req, res, next) {
try {
const users = await DB.User.find({});
if (!users) {
Logger.error('User was not found');
return res.status(404).send('Nothing found');
}
// Set users to redis
await Client.setex(users, 3600, users);
Logger.info('All the users were found');
return res.status(200).send(users);
} catch (err) {
Logger.error(err);
return next(err);
}
},}
The middleware:
import Client from '../loaders/redis';
// Cache middleware
const cache = (req, res, next) => {
const { users } = res;
Client.get(users, (error, cachedData) => {
if (error) throw error;
if (cachedData != null) {
res.send(users, cachedData);
} else {
next();
}
});
};
export default cache;
The route:
import Controller from '../controllers';
import cache from '../middleware/cacheMiddle';
app.get('/users', cache, Controller.UserCtrl.getAllUsers);
I cannot understand how to use it as I want to adopt Redis to bee able to get the users faster and also I don't know if make sense and also how to do it for the post of a user for example.