I'm using bluebird in NodeJS. I want to do a nested loop. Something like this:
var Promise = require('bluebird');
funcs.getLatestVideos = function(job, done) {
return Promise.try(function() {
return ProcessRules.getLatestVideos();
})
.then(function(object) {
return ({
'series': ProcessRules.getSeriesRules(),
'videos': object.videos
});
})
.then(function(inputs) {
return Promise.map(inputs.videos, function(video) {
return Promise.map(inputs.series, function(series) {
return Promise.map(series.rules, function(rule) {
return ProcessRules.processRules(video, rule);
});
});
})
})
.then(function(result) {
W.debug("done");
console.log(JSON.stringify(result));
done();
})
.catch(function(err) {
done(err);
W.error("Error occurred ", err.message, err.stack);
});
}
ProcessRules
var Promise = require('bluebird');
var rp = require('request-promise');
var W = require('winston');
var RuleEngine = require('node-rules');
var _ = require('lodash');
funcs.getSeriesRules = function() {
return new Promise(function(resolve, reject) {
var options = {
method: "GET",
uri: API_URL,
// body: status,
json: true // Automatically stringifies the body to JSON
};
rp(options)
.then(function(result) {
resolve(result)
})
.catch(function(err) {
reject(err)
});
});
};
funcs.processRules = function(fact, rule) {
return new Promise(function(resolve, reject) {
var rules = [];
var value = new RegExp(rule.value, 'i');
switch (rule.type) {
case 'title':
rules = [{
"condition": function(R) {
// console.log(this.title.match(value));
R.when(this.title.match(value) > -1);
},
"consequence": function(R) {
this.result = false;
this.video = R;
R.stop();
}
}];
break;
case 'desc':
rules = [{
"condition": function(R) {
//console.log(this.desc.match(value));
R.when(this.desc.match(value) > -1);
},
"consequence": function(R) {
this.result = false;
this.video = R;
R.stop();
}
}];
break;
case 'tag':
rules = [{
"condition": function(R) {
// console.log(this.tag.match(value));
R.when(!_.some(this.tags, { 'text': rule.value}))
},
"consequence": function(R) {
this.result = false;
this.video = R;
R.stop();
}
}];
break;
default:
break
};
//initialize the rule engine
const R = new RuleEngine(rules);
//Now pass the fact on to the rule engine for results
R.execute(fact, function(result) {
//console.log(result);
if (result.result) {
resolve(result._id)
}else{
resolve({})
}
});
});
};
It returns me following output
[[[{},{},"58e9d6816961c30367b5154c"],[{}],[],[],[]],[[{},{},"58e9d6816961c30367b5154d"],[{}],[],[],[]]]
But I am expecting with following output:
[58e9d6816961c30367b5154c,58e9d6816961c30367b5154d]
I see some similar question but not getting exact ideas from them.
In getLatestVideos function not able to get done result ,Please help me to resolve this issue.
Please help me to implement nested each loop with bluebird promise.
After long search with multiple questions and answers , I got the answer by Flattening a Promise map.
I don't know exactly its right way but its working for me.
.then(function(inputs) {
return Promise.map(inputs.videos, function(video) {
return Promise.map(inputs.series, function(series) {
return Promise.map(series.rules, function(rule) {
return ProcessRules.processRules(video, rule);
}).reduce(function(prev, cur) {
return cur ? prev.concat(cur) : [];
}, [])
}).reduce(function(prev, cur) {
return prev.concat(cur);
}, [])
}).reduce(function(prev, cur) {
return prev.concat(cur);
}, [])
})
It returns me [58e9d6816961c30367b5154c,58e9d6816961c30367b5154d].
Thanks Everyone.
Related
I need to fix the error on code below, can someone help me please?. The code is written on JS(NodeJs). The error is this (...).then is not a function. Thanks.
try {
var decoded = jwt.decode(JWTToken, { complete: true });
var audience = decoded.payload.aud;
return db.checkAudience(audience).then(ehClient => {
if (ehClient == true) {
return db.getCreditsGeneral(sgecode, collections, year).then(total => {
let result = [];
total.forEach(item => {
result.push({
collection: item.Sistema,
levelType: item.idNivelEnsino,
grade: item.codPortal
});
});
return result;
});
} else {
return "not authorized";
}
});
} catch (err) {
return { erro: err.message };
}
I have two js files. i am able to get data from mongodb by calliing bookDao.getActiveBookByCategoryId().
My Problem
In categoryDao.js file i am trying to update resultJson.book_countinside BookDao.getActiveBookByCategoryId() method. but it is not updating. So may i know how to fix this.
here book_count property in resultJson is still 0.
categoryDao.js
module.exports.getAllActiveCategory = (callback) => {
Category.find({
is_delete : false
}, (error, result) => {
if(error) {
console.log(error);
callback(commonUtil.ERROR);
}
if(result) {
var categoryArray = [];
for(var i=0; i<result.length; i++) {
var categorySingle = result[i];
var resultJson = {
_id : categorySingle._id,
category_name : categorySingle.category_name,
created_on : categorySingle.created_on,
book_count : 0
}
BookDao.getActiveBookByCategoryId(categorySingle._id, (bookResult) => {
if(bookResult) {
if(bookResult.length > 0) {
resultJson.book_count = bookResult.length;
}
}
});
categoryArray.push(resultJson);
}
callback(categoryArray);
}
});
}
bookDao.js
module.exports.getActiveBookByCategoryId = (categoryId, callback) => {
Book.find({
is_delete : false,
category : categoryId
}, (error, result) => {
if(error) {
console.log(error);
callback(commonUtil.ERROR);
}
if(result) {
callback(result);
}
});
}
Try this, In your code categoryArray.push(resultJson); will not wait for BookDao.getActiveBookByCategoryId to finish because of async behavior.
module.exports.getActiveBookByCategoryId = (categoryId) => {
return Book.count({
is_delete: false,
category: categoryId
});
}
module.exports.getAllActiveCategory = async () => {
try {
// Find all category
const result = await Category.find({
is_delete: false
});
// Create array of promise
const promises = result.map(categorySingle => BookDao.getActiveBookByCategoryId(categorySingle._id));
// Get array of Category count
const data = await Promise.all(promises);
// update count in result
return result.map((categorySingle, i) => {
categorySingle.book_count = data[i];
return categorySingle;
});
} catch (error) {
console.log(error);
}
}
I am trying to execute a callback in which only after getting the response it should execute the lines, starting from this.groupDefaultExpanded = -1; after that.
loadLoginDetails() {
this.derivativeSpecService.getDerivativeDetails().subscribe(
res => {
this.rowData = res;
this.groupDefaultExpanded = -1;
this.getDataPath = function(data) {
return data.orgHierarchy;
};
this.autoGroupColumnDef = {
headerName: "Name",
};
console.log(this.rowData);
})
}
derivativespec.ts
getDerivativeDetails(){
return this.http.get('assets/derivativespec.json').map((response: Response) => response);
}
Like this:
getDerivativeDetails(): Promise<Response> {
return this.http.get<Response>('assets/derivativespec.json').toPromise();
}
And then:
loadLoginDetails() {
this.derivativeSpecService.getDerivativeDetails().then(
res => {
this.rowData = res;
this.groupDefaultExpanded = -1;
this.getDataPath = function(data) {
return data.orgHierarchy;
};
this.autoGroupColumnDef = {
headerName: "Name",
};
console.log(this.rowData);
});
}
I am trying to write a function of mine using Bluebird promise Library.
I promisified the ldap-js the createClient function of ldap-js by:
var Promise= require('bluebird'); //done at the beginning
var createClientAsync = Promise.promisify(require('ldapjs').createClient);
getUser:function(user) {
var memberRoles = [];
var searchFilter = '(&(member='+user.dn+'))';
var opts = {
filter: searchFilter,
scope: 'sub',
attributes: ['dn']
};
createClientAsync({
url: 'ldap://x.x.x.x:3889'
})
.then(function(client){
return client.search('o=pic', opts);
})
.then(function(res) {
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
for (var role in roles) {
var mapping = roles[role];
if (mapping.group === entry.object.dn) {
memberRoles.push(role);
}
}
});
})
.then(function() {
return memberRoles;
});
}
I get an error at createClientAsync undefined is not a function.
After a brief reading of the ldapjs documentation, I can suggest the following code
getUser:function(user) {
var searchFilter = '(&(member='+user.dn+'))';
var opts = {
filter: searchFilter,
scope: 'sub',
attributes: ['dn']
};
return createClientAsync({
url: 'ldap://x.x.x.x:3889'
})
.then(function(client){
return client.search('o=pic', opts);
})
.then(function(res) {
var memberRoles = [];
return new Promise(function(resolve, reject) {
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
for (var role in roles) {
var mapping = roles[role];
if (mapping.group === entry.object.dn) {
memberRoles.push(role);
}
}
});
res.on('end', function() {
resolve(memberRoles);
});
});
});
}
note the "new Promise" and res.on('end' to resolve the promise once the "search" has completed
as I said, brief reading of documentation, so this may be completely invalid :p
I am writing an service, where I retrieve a list of items from a another service, then iterate over result performing keystone.list operation(s).
I am loosing the return status in the find/exec operation. I have tried promises, async, etc.
If someone could point out the correct way to implement this, I would appreciate it.
general implementation:
exports = module.exports = function (req, res) {
var rtn = {
added: 0,
count: 0
}
service(params)
.then(function(svcResult) {
svcResult.forEach(function(item) {
rtn.count++; // <-- correctly seen in apiresponse
Artifact.model.find()
.where({ artifactId: item.id})
.exec(function(err, result) {
if (result.length == 0) {
result = new Artifact.model({
... populate from item ....
});
result.save();
rtn.added++; // <-- not seen in api response
});
});
res.apiResponse(rtn);
});
}
for starters, exec is an async call, which you are ignoring in your res.apiResponse and thus count is incremented and not added, to make life easy, I am moving the exec call outside and wrapping it with promise:
function pExec(id){
return new Promise(function(resolve, reject){
Artifact.model.find()
.where({ artifactId: id})
.exec(function(err, result){
console.log('result: ', result); // there is a possibility that this is not empty array, which seems to be the only case when you increment added value
err? reject(err): resolve(result);
});
});
}
exports = module.exports = function(req, res){ // I think it is 'exports' not 'exposts'
service(params)
.then(function(svcResult) {
var promises = svcResult.map(function(item){
rtn.count++;
return pExec(item.id).then(function(result){
if (result.length == 0) {
result = new Artifact.model({
//... populate from item ....
});
result.save(); // again this might be an async call whose response you might need before incrementing added...
rtn.added++; // <-- not seen in api response
};
});
});
Promise.all(promises).then(function(){
res.apiResponse(rtn);
});
});
}
Thanks... Here is what I have come up with so far....
function getArtifact(id) {
return new Promise(function (resolve, reject) {
Artifact.model.findOne()
.where({artifactId: id})
.exec(function (err, artifact) {
err ? resolve(null) : resolve(artifact);
});
});
}
function createArtifact(item) {
return new Promise(function (resolve, reject) {
var artifact = new Artifact.model({
// ... populate from item ....
});
artifact.save(function (err, artifact) {
err ? resolve(null) : resolve(artifact);
});
});
}
exports = module.exports = function (req, res) {
var rtn = {
success: false,
count: 0,
section: '',
globalLibrary: {
Added: 0,
Matched: 0
},
messages: [],
};
if (!req.user || !req.user._id) {
rtn.messages.push("Requires Authentication");
return res.apiResponse(rtn);
}
if (!req.params.section) {
rtn.messages.push("Invalid parameters");
return res.apiResponse(rtn);
}
var userId = req.user._id;
var section = req.params.section;
rtn.section = section;
service(section)
.then(function (svcResult) {
if (svcResult.length == 0 || svcResult.items.length == 0) {
rtn.messages.push("Retrieved empty collection");
return;
}
rtn.messages.push("Retrieved collection");
var artifacts = svcResult.items(function (item) {
rtn.count++;
return getArtifact(item.objectid)
.then(function (artifact) {
if (!artifact || artifact.length == 0) {
rtn.messages.push("Global Library Adding: " + item.name['$t']);
rtn.globalLibrary.Added++;
artifact = createArtifact(item);
} else {
rtn.globalLibrary.Matched++;
}
return artifact;
})
});
Promise.all(artifacts)
.then(function () {
rtn.success = true;
res.apiResponse(rtn);
});
});
}