So I'm sending data properly to mongo and data (user input information), which is correctly held in backend. In console I'm getting interceptor that tells me that data is received from Mongo DB, but how to properly get those properties (user's email, title of photo and url blob) or 'data'? So it can be seen as individual data (email, title...) and not as the whole object like it can be seen in console now.
--THIS IS IN MY VUE--
dohvatiObjavu(){
this.objava = Objave.dohvati_objavu();
console.log("Current post " + this.objava);
}
},
-- THIS IS IN SERVICES--
[let Objave = {
async dohvati_objavu() {
let response = await Service.get(/galerija)
let data = response.data;
console.log("Current posts in services: "+data.naslov)
return {
id: data._id,
email: data.email,
naslov: data.naslov,
noviOpisSlike: data.noviOpisSlike,
slika: data.slikaReference,
}
},
}
--THIS IS IN BACKEND--
app.get ('/galerija', async (req , res) => {
let db = await connect();
let cursor = await db.collection('galerija').find();
let results = await cursor.toArray();
res.json(results);
});
-- MY CONSOLE--
Objave.dohvati_objavu(); is an async function. So you should also await this inside your Vue method dohvatiObjavu().
I created a simplified working example, based on your code:
const Objave = {
dohvati_objavu: async function() {
// mock Service.get(/galerija) with Promise.resolve
const data = await Promise.resolve({
id: 'mockId',
email: 'mockEmail',
naslov: 'mockNaslov',
noviOpisSlike: 'mockNoviOpisSlike',
slika: 'mockSlika',
});
return {
id: data._id,
email: data.email,
naslov: data.naslov,
noviOpisSlike: data.noviOpisSlike,
slika: data.slikaReference
}
}
}
const MyVueComponent = class {
objava = undefined;
// DOES NOT WORK
dohvatiObjavu() {
this.objava = Objave.dohvati_objavu();
console.log("[dohvatiObjavu] Current post ", this.objava);
}
// WORKS
async dohvatiObjavu2() {
this.objava = await Objave.dohvati_objavu(); // <!-- await
console.log("[dohvatiObjavu2] Current post ", this.objava);
}
}
const component = new MyVueComponent()
component.dohvatiObjavu();
component.dohvatiObjavu2();
Related
am trying to save a data from fetch api to my database using mongoose so
the data never come.
could anyone help? and thank you,
this is my code
`
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/Quran')
const SurahSchema = mongoose.Schema({
ayahs:[{
number:Number,
numberInSurah:Number,
text:String
}],
englishName:String,
englishNameTranslation:String,
name:String,
number:Number,
revelationType:String,
});
var surah = mongoose.model('Surah',SurahSchema)
`
`
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani'
async function getdata(){
const res = await fetch(API)
const data = await res.json()
for (let i = 0; i < data.data.surahs.length; i++) {
const Surah = new surah({
ayahs:[{
number:data.data.surahs[i]['ayahs'].number,
numberInSurah:data.data.surahs[i]['ayahs'].numberInSurah,
text:data.data.surahs[i]['ayahs'].text
}],
englishName:data.data.surahs[i]['englishName'],
englishNameTranslation:data.data.surahs[i]['englishNameTranslation'],
name:data.data.surahs[i]['name'],
number:data.data.surahs[i]['number'],
revelationType:data.data.surahs[i]['revelationType']
})
Surah.save(function (err) {
if (err) return handleError(err);
// saved!
});
}
}
getdata()
`
i tried to search about the problem in google and i did not find anything similar.
Instead of writing such a complicated for loop, you can just use the .insertMany() method on the model
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani'
async function getdata(){
const res = await fetch(API);
const data = await res.json();
try{
const inserted = await surah.insertMany(data.data.surahs);
}catch(e){
console.log("Some error");
console.log(e);
}
}
getdata()
the following is a complete working snippet
import mongoose from 'mongoose';
import fetch from 'node-fetch';
mongoose.connect('mongodb://localhost:27017/Quran');
const SurahSchema = mongoose.Schema({
ayahs: [
{
number: Number,
numberInSurah: Number,
text: String,
},
],
englishName: String,
englishNameTranslation: String,
name: String,
number: Number,
revelationType: String,
});
const surah = mongoose.model('Surah', SurahSchema);
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani';
async function getdata() {
const res = await fetch(API);
const data = await res.json();
try {
const inserted = await surah.insertMany(data.data.surahs);
console.log(inserted);
process.exit(0);
} catch (e) {
console.log('Some error');
console.log(e);
process.exit(0);
}
}
getdata();
this inserted 114 documents
PS: you just need to install node-fetch and mongoose
Inside my userDB.json file it looks like this;
[{
"username": "john",
"xp": 5
},
{
"username": "jane",
"xp": 0
}
]
Inside the app.js file ;
async function getUsers() {
let url = 'userDB.json';
try {
let res = await fetch(url);
return await res.json();
} catch (error) {
console.log(error);
}
}
async function addUser(username){
let users = await getUsers();
let newUser = {"username": `${username}`,"xp": 0};
users.push(newUser);
}
addUser('testName');
async function renderUsers() {
let users = await getUsers();
let html = '';
users.forEach(user => {
let htmlSegment = `<div class="user">
<h2>${user.username} ${user.xp}</h2>
</div>`;
html += htmlSegment;
});
let container = document.querySelector('.container');
container.innerHTML = html;
}
renderUsers();
I would like to send a data to my local database and save it then I would like to render database array items on screen. But when I console.log the users in addUser() function added item visible on console but not rendered or saved on local file how to do that?
What you are doing in addUser() is to get the array from your database, mutating it by pushing a new item in it, but that only affects that specific array you got, not the database.
For this to work you need to make a post request to a backend that would update your database and then call renderUsers() to get the updated data:
async function addUser(username) {
let url = "/"; // ⚠️ whatever url that accept a post request
let newUser = { username: username, xp: 0 };
await fetch(url, { method: "POST", body: JSON.stringify(newUser) });
renderUsers();
}
I'm having a problem right now when i want to remove some code out of my route to put it into a service. I'm just trying to follow the best practices of developing an application.
This is my route right now:
const express = require('express');
const cityRouter = express.Router();
const axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();
cityRouter.get('/:cep', async (request, response) => {
try {
const { cep } = request.params;
const value = myCache.get(cep);
if (value) {
response.status(200).send({
city: value,
message: 'Data from the cache',
});
} else {
const resp = await axios.get(`https://viacep.com.br/ws/${cep}/json/`);
myCache.set(cep, resp.data, 600);
response.status(200).send({
city: resp.data,
message: 'Data not from the cache',
});
}
} catch (error) {
return response.status(400);
}
});
module.exports = cityRouter;
I'm using axios to retrieve data from an API, where i have a variable called "cep" as a parameter and then using node-cache to cache it.
And it works with out problems:
enter image description here
But, when i try to put the same code into a service, and then call it into my route:
My service:
const axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();
function verificaCache(cep) {
return async function (request, response, next) {
const value = myCache.get(cep);
console.log(cep);
if (value) {
response.status(200).send({
city: value,
message: 'Data from the cache',
});
} else {
const resp = await axios.get(`https://viacep.com.br/ws/${cep}/json/`);
myCache.set(cep, resp.data, 600);
response.status(200).send({
city: resp.data,
message: 'Data not from the cache',
});
}
next();
};
}
module.exports = verificaCache;
My route using the service:
const express = require('express');
const cityRouter = express.Router();
const verificaCache = require('../services/VerificaCacheService');
cityRouter.get('/:cep', async (request, response) => {
const { cep } = request.params;
verificaCache(cep);
response.status(200);
});
module.exports = cityRouter;
By some reason, it doesn't work:
enter image description here
What is the problem that i can't see? I'm a beginner so i'm kinda lost right now.
You have created a high-order function by returning a function in verificaCache(), so to properly call it you need to do it like that await verificaCache(cep)(req, res), remember, the first time you call it, you have a function being returned, since you want the tasks inside of that function to be executed, you need to call it as well.
Take a reading about high-order functions here: https://blog.alexdevero.com/higher-order-functions-javascript/
My recommendation, you could just get rid of the other function you are returning to simplify your code, and let the service only handle business logic, all the http actions should be handled on the controller level:
// Service
function verificaCache(cep) {
const value = myCache.get(cep);
if (value) {
return { city: value, message: 'Data from the cache'})
}
// No need of an else statement because the
// execution will stop at the first return if the condition passes
const resp = await axios.get(`https://viacep.com.br/ws/${cep}/json/`);
myCache.set(cep, resp.data, 600);
return { city: resp.data, message: 'Data not from the cache'};
}
// Controller
cityRouter.get('/:cep', async (request, response) => {
const { cep } = request.params;
try {
const data = verificaCache(cep);
// Use json() instead of send()
response.status(200).json(data);
} catch(error) {
// Handle errors here
console.log(error);
}
});
Estamos juntos!
I'm creating API tests with async-await using Supertest and Mocha.
In the accountsData.js file I created a function to generate random test accounts.
In the accountsHelper.js file I created a function to create unlimited accounts using a while loop
When I run tests on the post_accounts.js file, the first account is created successfully, but from the second account, the data generated in the accountsData.js file is already repeated.
Why isn't data randomly generated when I create more than one account using data from the accountsData.js file?
accountsData.js
const casual = require('casual');
function randomAccount() {
return {
'email': casual.email,
'password': '123456',
};
}
module.exports = {
randomAccount,
};
accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
/* eslint-disable no-console */
const accountList = [];
let counterAccounts;
module.exports = {
async createAccount(account, accountsToCreate = 2, validateResponse = true) {
counterAccounts = 0;
while (counterAccounts < accountsToCreate) {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
.send(account);
if (validateResponse === true) {
if (res.status === commonData.statusCode.ok) {
accountList.push(res.body);
} else {
throw new Error('Email already exists\n\n' + JSON.stringify(res.body, null, ' '));
}
} else {
return res.body;
}
} catch (err) {
console.log(err);
}
counterAccounts++;
}
return accountList;
},
};
post_accounts.js
const accountsData = require('../../data/accountsData');
const accountsHelper = require('../../helpers/accountsHelper');
const account = accountsData.randomAccount();
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async() => {
const res = await accountsHelper.createAccount(account);
// eslint-disable-next-line no-console
console.log(res);
});
});
});
API response:
Create accounts with email and password
valid accounts
Error: Email already exists
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `account` instance is not valid. Details: `email` Email already exists (value: \"Lemuel.Lynch#Susan.net\").",
"details": {
"context": "account",
"codes": {
"email": [
"uniqueness"
]
},
"messages": {
"email": [
"Email already exists"
]
}
}
}
}
at Object.createAccount (/Users/rafael/Desktop/projects/services/test/helpers/accountsHelper.js:24:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ { 'privacy-terms': false,
'created-date': '2019-08-24T10:00:34.094Z',
admin: false,
isQueued: false,
lastReleaseAttempt: '1970-01-01T00:00:00.000Z',
'agreed-to-rules': { agreed: false },
email: 'Lemuel.Lynch#Susan.net',
id: '5d610ac213c07d752ae53d91' } ]
✓ should create an account successfully (2243ms)
1 passing (2s)
The code that you posted doesn't correspond to the code that you're describing in prose.
However, I tested your accountsData.js file, in the way that your words (but not your code) say that you're using it, and it works fine.
// main.js
const { createPerson } = require(__dirname + '/accountsData')
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
Output from running it once:
$ node main.js
{ email: 'Anne_Ebert#Macie.com', password: '123456' }
{ email: 'Manley.Lindgren#Kshlerin.info', password: '123456' }
{ email: 'McClure_Thurman#Zboncak.net', password: '123456' }
{ email: 'Breitenberg.Alexander#Savannah.com', password: '123456' }
{ email: 'Keely.Mann#Stark.io', password: '123456' }
And again:
$ node main.js
{ email: 'Destany_Herman#Penelope.net', password: '123456' }
{ email: 'Narciso_Roob#gmail.com', password: '123456' }
{ email: 'Burnice_Rice#yahoo.com', password: '123456' }
{ email: 'Roma_Nolan#yahoo.com', password: '123456' }
{ email: 'Lilla_Beier#yahoo.com', password: '123456' }
Nothing in the code that you posted is actually requiring or using accountsData.js. If you change your code to use it, I think you'll see, like I do, that it works.
Problem is, you are generating the random account and storing it in a variable 'post_accounts.js(line 3)'. So, when you create an account, you are using the same payload to create multiple accounts, which obviously throws an error.
I just modified the accountHelper to properly handle your scenario. Hope this helps.
Note: The code is not tested, I just wrote it from my mind. Please test and let me know if it works.
// accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
const accountsData = require('../../data/accountsData');
/* eslint-disable no-console */
const accountList = [];
module.exports = {
async createAccount(account, accountsToCreate = 1, validateResponse = true) {
// creates an array of length passed in accountsToCreate param
return (await Promise.all(Array(accountsToCreate)
.fill()
.map(async () => {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
// takes account if passed or generates a random account
.send(account || accountsData.randomAccount());
// validates and throw error if validateResponse is true
if (validateResponse === true && (res.status !== commonData.statusCode.ok)) {
throw new Error(
'Email already exists\n\n' +
JSON.stringify(res.body, null, ' ')
);
}
// return response body by default
return res.body;
} catch (e) {
console.error(e);
// return null if the create account service errors out, just to make sure the all other create account call doesnt fail
return null;
}
})))
// filter out the null(error) responses
.filter(acc => acc);
}
};
//post_accounts.js
const accountsHelper = require('../../helpers/accountsHelper');
const accountsData = require('../../data/accountsData');
const GENERATE_RANDOM_ACCOUNT = null;
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async () => {
const result = await accountsHelper.createAccount();
expect(result.length).toEquals(1);
});
it('should create 2 accounts successfully', async () => {
const result = await accountsHelper.createAccount(GENERATE_RANDOM_ACCOUNT, 2);
expect(result.length).toEquals(2);
});
it('should not create duplicate accounts', async () => {
const account = accountsData.randomAccount();
// here we are trying to create same account twice
const result = await accountsHelper.createAccount(account, 2);
// expected result should be one as the second attempt will fail with duplicate account
expect(result.length).toEquals(1);
});
});
});
how do I post to referenced schemas in mongodb while using async-await. i was able to create the get function but i am having a hard time creating the post and the put.
here is my get function :
I think, in your request body you should only pass issue id and user id. So when you get the task with your get task details API, mongoose will prepopulate the data.
Your request body should look like
{
issue: "5ca2b1f80c2e9a13fcd5b913",
user: "5ca2b1f80c2e9a13fcd5b90b",
record: {
votary: 80,
development: 90,
test: 100
},
date: "2019-03-01T15:00:00.000Z"
};
And then save the task details as
try {
const task = new TaskModel(req.body);
const result= await task.save()
return api.responseJSON(res, 200, result);
} catch (e)
{
// Error
}
Just wrap the code inside of post in a try/catch
export const post: Operation = async (req: express.Request, res: express.Response) => {
try {
const param: any = {};
const task = new TaskModel(req.body);
const newTask = await task.save()
return api.responseJSON(res, 200, newTask);
} catch(err) {
// treat error
}
}
You should not save the complete req.body instead save only those fields which your schema accepts. And according to Task schema issue and user fields should store id but not the complete object which is there in req.body. Please try this and update your post method accordingly:
export const post: Operation = async (req: express.Request, res: express.Response) => {
try {
let param: any = {};
const user = {
id: req.body.user.id
};
const issue = {
id: req.body.issue.id
};
param = req.body;
param.user = user.id
param.issue = issue.id
const task = new TaskModel(param);
const newTask = await task.save()
return api.responseJSON(res, 200, newTask);
} catch (e) {
api.responseJSON(res, 400, e)
}
};