How do I pass values from a Promise.all to .then()? - javascript

I have a promise chain that first collects contact objects and then processes the collected contacts. How can I pass the contacts to the .then() section after Promise.all()?
let collectUserDataPromise = []
allUsers.forEach((userId) => {
//Collect all contacts
collectUserDataPromise.push(
dbRoot.child(`users/${userId}`)
.once('value', (userSnapshot)=>{
const userNodeData = userSnapshot.val()
const contactObject = {
alias: (userNodeData.alias) ? userNodeData.alias : '',
name: (userNodeData.name) ? userNodeData.name : '',
status: 'active'
}
console.log('contactObject', contactObject)
//return contactObject
return new Promise((resolve, reject)=> resolve([contactObject]))
})
)
})
Promise.all(collectUserDataPromise)
.then((contactObjects)=>{
console.log('contactObjects', contactObjects)
My log shows that I have collected the objects correctly but that I cannot seem to pass then to the .then() section on last row in my code example.
Log from the .once() section
"contactObject { alias: 'Donald', name: 'Donald D', status: 'active'}"
"contactObject { alias: 'Mickey', name: 'Mickey M', status: 'active' }"
Log from the .then() section
"contactObjects [ DataSnapshot {
node_:
ChildrenNode {
children_: [Object],
priorityNode_: [Object],
indexMap_: [Object],
lazyHash_: null },
ref_:
Reference {
repo: [Object],
path: [Object],
queryParams_: [Object],
orderByCalled_: false },
index_: PriorityIndex {} },
DataSnapshot {
node_:
ChildrenNode {
children_: [Object],
priorityNode_: [Object],
indexMap_: [Object],
lazyHash_: null },
ref_:
Reference {
repo: [Object],
path: [Object],
queryParams_: [Object],
orderByCalled_: false },
index_: PriorityIndex {} },
DataSnapshot {
node_:
ChildrenNode {
children_: [Object],
priorityNode_: [Object],
indexMap_: [Object],
lazyHash_: null },
ref_:
Reference {
repo: [Object],
path: [Object],
queryParams_: [Object],
orderByCalled_: false },
index_: PriorityIndex {} } ]"
timestamp: "2019-09-08T18:50:40.259Z"
trace: "projects/xxxx/xxx"
}"
How can I pass all the collected values from Promise.all() to the .then() section of the promise chain?

It looks like the dbRoot.child('...').once('...') portion of your code is essentially the Promise you want to store in the collectUserDataPromise array. This means you shouldn't need to create your own Promise as you have done (return new Promise etc).
Try the following and let me know it that helps:
let collectUserDataPromise = [];
allUsers.forEach(userId => {
//Collect all contacts
collectUserDataPromise.push(
dbRoot
.child(`users/${userId}`)
.once("value")
.then(userSnapshot => {
const userNodeData = userSnapshot.val();
const contactObject = {
alias: userNodeData.alias ? userNodeData.alias : "",
name: userNodeData.name ? userNodeData.name : "",
status: "active"
};
//return contactObject
return contactObject;
})
);
});
Promise.all(collectUserDataPromise).then(contactObjects => {
console.log("contactObjects", contactObjects);
});

Related

how do i check if hits has a value or not?

My goal is to send an alarm if the [hits] field is empty.
This is my result:
hits: {
total: { value: 10000, relation: 'gte' },
max_score: 1,
hits: [
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object],
[Object], [Object]
]
}
}
and this is my code:
const axios = require('axios');
const query = {
query: {
match: {
"kubernetes.pod.name.keyword" : "fcppaddy-596b798c77-9hwbh"
}
}
};
axios.get("https://tommaso.fachin:Indigestione!#elastic.gnet.it:9200/filebeat-7.15.2/_search?
pretty", query)
.then((res) => {
console.log(res.data);
console.log(res.status);
console.log(JSON.stringify(res.data));
});
I'm still not 100%, but from your comments it seems like you want to check if hits has anything in it, and if so do something for each one:
if(hits.length > 0) {
hits.forEach((hit) => {
triggerAlarm()
})
}
So obviously you can choose what to send as a param to triggerAlarm() but I think this is what you're asking for
Edit, based on your comment:
if(hits.hits.length > 0) {
hits.forEach((hit) => {
// for each item in hits.hits array, send mail
ModuloMail()
})
}

Knex.js return inserted record ID

I am inserting a note into the quoteNotes table. When I insert it and console log the res. it doesn't give me a record of the inserted note.
router.post('/:id/notes', (req, res) => {
const {id} = req.params;
const note = req.body;
note.quote_id = id
// if(note.note === "") return res.status(422)
// .json({message: 'Note cannot be empty'});
Quotes.addNote(note).then((quoteNote) => {
console.log(quoteNote)
res.status(200).json(quoteNote);
});
});
console.log =>
Result {
command: 'INSERT',
rowCount: 1,
oid: 0,
rows: [],
fields: [],
_parsers: undefined,
_types: TypeOverrides {
_types: {
getTypeParser: [Function: getTypeParser],
setTypeParser: [Function: setTypeParser],
arrayParser: [Object],
builtins: [Object]
},
text: {},
binary: {}
},
RowCtor: null,
rowAsArray: false
}
Figured it out.
needed to add .returning('id') to the query.
function addNote(data) {
return db('quote_notes')
.insert(data)
.returning('id');
}
In my case with mysql, the await insert({...}) returned an array with an id as a single element. And by using returning('id') I got an error saying it's not supported for mysql.

Why does returning snapshot.val() in a Promise when using Promise.all not work?

I'm writing a Firebase Cloud Function and I'm trying to figure out how Promise.all works. In my code, I pass in an array of database queries and I'm trying the read the resulting array, but I'm only getting garbage:
T {
A:
P {
k: Sb { Ka: [Function: vb], ba: [Object] },
aa: P { k: [Object], aa: null, wb: [Object], Bb: '' },
wb: Zc { ld: [Object], ac: [Object] },
Bb: null },
V:
R {
u:
Gd {
app: [Object],
L: [Object],
Ua: [Object],
Sc: null,
ca: [Object],
td: 1,
Qa: [Object],
va: [Object],
qg: [Object],
jc: [Object],
ee: [Object],
md: [Object],
ia: [Object],
Xa: [Object],
cd: 2,
fe: null,
K: [Object] },
path: J { o: [Object], Y: 0 },
m:
Df {
xa: false,
ka: false,
Ib: false,
na: false,
Pb: false,
oa: 0,
kb: '',
bc: null,
xb: '',
Zb: null,
vb: '',
g: Tc {} },
Kc: false,
then: undefined,
catch: undefined },
g: Tc {} }
I'm expecting a simple json:
{
"name": "Foo",
"number": 2521
// And a few other fields
}
BTW, I watched Jen's video so I know what I'm doing is wrong anyway; I just want to know why my existing code doesn't work. (I haven't tested it, but I believe the solution is to return the raw snapshots in my db query and then do the .val() call.)
Relevant code if the links disappear:
function mergeTeams(duplicates) {
return Promise.all([
admin.database().ref(someRef).once('value', (snap) => {
return snap.val();
}),
admin.database().ref(someRef2).once('value', (snap) => {
return snap.val();
})
]).then(values => {
console.log(values);
const team1 = values[0];
const team2 = values[1];
console.log(team1);
console.log(team2);
}
So, here's the code that works (and the explanation below):
return Promise.all([
admin.database().ref(teamRef + duplicates.teamKey1).once('value'),
admin.database().ref(teamRef + duplicates.teamKey2).once('value')
]).then(values => {
const team1 = values[0].val();
const team2 = values[1].val();
console.log(team1);
console.log(team2);
});
The reason it works is because I've always getting the promises in the values array even though I didn't know it. Here's what Promise.all returns: an array with the raw result of the promises passed in. When I was returning stuff inside the success callback, that didn't actually do anything because it wasn't part of the promise; I was just returning random stuff to an empty void. And when I was printing the teams, I was actually logging the Firebase Snapshot object instead of the .val().

Body response to client(Angular2) from Node API via Express formatted wrong

When my Angular2 component makes a request to get my fake model data object it gets returned like so:
_body: "[↵ {↵ "id": 0,↵ "title": "2017 Oscars",↵ "graphic": "https://wikitags.com/images/OscarsBanner.png",↵
What I am expecting is an Array like so:
[
{ id: 0,
title: '2017 Oscars',
graphic: '/images/OscarsBanner.png',
categorycards: [ [Object], [Object], [Object], [Object] ] },
{ id: 1,
title: '2017 Super Bowl',
graphic: '/images/SuperBowlBanner.png',
categorycards: [ [Object], [Object], [Object], [Object] ] },
{ id: 2,
title: 'What people are talking about',
graphic: null,
categorycards: [ [Object], [Object], [Object], [Object] ] }
]
The Model
What my backend/models/home.ts looks like
export function homeData() {
return [
{
id: 0,
title: '2017 Oscars',
graphic: '/images/OscarsBanner.png',
categorycards: [
{
type: 'image',
graphic: 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Ryan_Gosling_2_Cannes_2011_%28cropped%29.jpg/1024px-Ryan_Gosling_2_Cannes_2011_%28cropped%29.jpg?width=440',
title: '2017 Oscar Nominee for Best Actor',
listings: ['Rayn Gosling', 'Denzel Washington', 'Andrew Garfield', 'Casey Affleck', 'Viggo Mortensen']
}
//...
]
}
//...
];
}
The client API
api.service.ts
#Injectable()
export class ApiService {
private getFeaturedUrl: string = '/wiki/api';
constructor(public http: Http) {}
/**
* Get featured categories data for homepage
*/
getFeatured(): Observable<{}> {
return this.http.get(`${this.getFeaturedUrl}/home`)
.do(res => console.log('getFeatured res', res))
.map(res => res.json().data)
.catch(this.handleError);
}
The console.log here:
The homepage component
universalInit() {
console.log('universalInit...')
this.api.getFeatured()
.subscribe(categories => {
console.log('categories', categories);
// this.testFeaturedCategories = categories
});
The Node/Express API endpoint
// API CRUD ////////////////////////////////////////////////////////////////////
app.get('/wiki/api/home', (req, res) => {
console.log('homeData()', homeData());
if (!homeData()) returnError(res, 'No home data found');
res.json(homeData());
});
In the terminal, I see my home.ts model Array:
Any ideas why my res.body is looking jacked up?
It looks like it may be trying to convert the json object twice. Not completely sure though
instead of res.json(homeData())
Try:
res.send(homedata())
If that doesn't work, then my guess would be to go on the angular side and change
.map(JSON.parse(res.json().data))

Node.js - Counting the number of objects in MongoDB collection

I am new to Node.js and MongoDB and I am really struggling to wrap my head around callbacks. I have read a few articles but it is still quite confusing to me. In the code below, I am trying to return the count of orders that have some properties which I have expressed in the query in orderModel.count(query, next):
controllers/order.js:
var mongoose = require ('../config/db');
var orderModel = require('../models/order').model;
var User = require('./user');
var Error = require('../config/error');
createOrder: function (user, order, next) {
if (newOrder.totalPrice > user.credit && orderModel.
count({$and: [{user: order.user}, {active: true}, {$or: [{status: 0}, {status: 1}]}]},
function(err, count){
if(err)
console.log(err);
else
count; }) > 0)
return next({error: Error.InsufficientCredits});
}
I don't think I am correctly obtaining the variable count because when I tried printing out the result of the second condition in the if statement, I got this data printed out:
Query {
_mongooseOptions: {},
mongooseCollection:
NativeCollection {
collection: Collection { s: [Object] },
opts: { bufferCommands: true, capped: false },
name: 'orders',
collectionName: 'orders',
conn:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
hosts: null,
host: 'dsXXXXXX.mlab.com',
port: XXXXXX,
user: 'XXXX',
pass: 'XXXX',
name: 'X',
options: [Object],
otherDbs: [],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
db: [Object],
_events: {},
_eventsCount: 0 },
queue: [],
buffer: false,
emitter:
EventEmitter {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined } },
....
You need to put your logic inside the Model.count() method callback function as:
var mongoose = require ('../config/db'),
orderModel = require('../models/order').model,
User = require('./user'),
Error = require('../config/error');
var createOrder = function (user, order, next) {
orderModel.count({
"user": order.user,
"active": true,
"status": { "$in": [0, 1] }
}, function(err, count) { //<-- put logic in this callback
if (err) {
console.log(err);
throw err;
} else if (newOrder.totalPrice > user.credit && count > 0) {
// logic for creating order here
} else {
return next({ "error": Error.InsufficientCredits });
}
})
}

Categories