Repeat data redundant variable - javascript

I have two functions that I declare the same variable twice. My code works but its not the most efficient, Can someone help me restructure the code so that I may set once and use it twice rather than setting it twice.
I was thinking something like this. but its not working
var promise = new Promise(function (resolve) // repeat code
function () {
promise. { code }
Code
As you can see bellow var promise = new Promise(function (resolve) is repeated in the first and second function, I feel this is not the most efficient way of writing this.
var firstFunction = function () {
var promise = new Promise(function (resolve) {
setTimeout(function () {
app.post('/test.js', function (req, res) {
console.log(req.body);
var login = req.body.LoginEmail;
res.send(login);
resolve({
data_login_email: login
});
});
console.error("First done");
}, 2000);
});
return promise;
};
var secondFunction = function () {
var promise = new Promise(function (resolve) {
setTimeout(function () {
nodePardot.PardotAPI({
userKey: userkey,
email: emailAdmin,
password: password,
DEBUG: false
}, function (err, client) {
if (err) {
console.error("Authentication Failed", err);
} else {
var api_key = client.apiKey;
console.log("Authentication successful !", api_key);
resolve({data_api: api_key});
}
});
console.error("Second done");
}, 2000);
});
return promise;
};

Related

ldapjs advanced search on subtree

Iam using ldapjs library for my project with standard LDAP server and iam trying to using search(). Its working right until i want to return results.
So i believe its more my misunderstanding of how javascript works rather than library as its working fine console.log
Secondly iam not sure if iam using nested search() correctly and efficiently.
Any help would be appreciated
function getPhones() {
return new Promise((resolve, reject) => {
let phones = [];
const opts = {
filter: `(objectClass=Phone)`,
scope: 'sub',
// attributes: ['*'],
};
client.search(`cn=${callserver.cn},cn=Modules`, opts, function (err, res) {
if (err) {
console.log('Error in promise', err);
}
res.on('searchEntry', function (entry) {
let newPhone = {};
const opts2 = {
filter: `(objectClass=*)`,
scope: 'sub',
};
client.search(`${entry.object.dn}`, opts2, function (err, res) {
res.on('searchEntry', function (entry2) {
newPhone = entry2.object;
console.log(newPhone); //here its logging just fine with all attributes
});
});
console.log(newPhone);// here newPhone is empty
phones.push(
{ ...entry.object, details: newPhone }
// followMeTo: entry.object.followMeTo,
// telephoneNumber: parseInt(entry.object.telephoneNumber),
);
});
res.on('end', function () {
resolve(phones);
});
res.on('err', function () {
reject('Error');
});
});
}
}
UPDATE 1:
if i try to use as suggested:
client.search(`${entry.object.dn}`, opts, function (err, res) {
res.on('searchEntry', function (entry2) {
phones.push({ ...entry.object, detail: entry2.object });
});
});
in here i cant access phones array, or nothing is pushed into it
so i have to do it this way:
client.search(`${entry.object.dn}`, opts, function (err, res) {
res.on('searchEntry', function (entry2) {
});
phones.push({ ...entry.object, detail: entry2.object });
});
but here i lose access to entry2 :-(
Losing my mind now
I am not familiar with this API, but it looks like your code would be something like this:
function getPhones() {
return new Promise((resolve, reject) => {
let phones = [];
const opts = {
filter: `(objectClass=Phone)`,
scope: "sub"
};
client.search(`cn=${callserver.cn},cn=Modules`, opts, function (err, res) {
if (err) {
console.log("Error in promise", err);
}
res.on("searchEntry", function (entry) {
const opts = {
filter: `(objectClass=*)`,
scope: "sub"
};
client.search(`${entry.object.dn}`, opts, function (err, res) {
res.on("searchEntry", function (entry2) {
phones.push({
...entry.object,
...{
details: entry2.object
}
});
});
});
res.on("end", function () {
resolve(phones);
});
res.on("err", function () {
reject("Error");
});
});
});
});
}
The problem with below code:
client.search(`${entry.object.dn}`, opts2, function (err, res) {
res.on('searchEntry', function (entry2) {
newPhone = entry2.object;
console.log(newPhone); //here its logging just fine with all attributes
});
});
console.log(newPhone);// here newPhone is empty
Is that JS executes client.search() which is an async action, and without waiting for the response continues to execute the console.log(newPhone);.
So the fix here would be to simply push phones into results when the response comes back, within the success callback.
Side note:You can also look into async await if you want to write the code that "looks" synchronous

The continuation token specified in the request is malformed

I'm really having a hard time trying to make pagination work with documentDB with the node SDK.
This is what i have:
find: function (querySpec) {
var self = this;
return new Promise((resolve, reject) => {
var options = {
maxItemCount: 2
}
var query = self.client.queryDocuments(self.collection._self, querySpec, options);
query.executeNext(function (err, results, headers) {
if (err) {
reject(err);
} else {
self.continuation = headers['x-ms-continuation'];
resolve({ 'results': results, 'resource': headers['x-ms-resource-usage'] });
}
})
});
},
nextPage: function () {
var self = this;
console.log(this.continuation)
return new Promise((resolve, reject) => {
var options = {
maxItemCount: 2
}
self.continuation ? options['continuation'] = self.continuation : '';
var query = self.client.readDocuments(self.collection._self, options);
query.executeNext(function (err, results, headers) {
if (err) {
reject(err);
} else {
resolve({ 'results': results, 'resource': headers['x-ms-resource-usage'] });
}
})
});
}
Continuation Token:
{"token":"-RID:K0JYAKIH9QADAAAAAAAAAA==#RT:1#TRC:2","range":{"min":"","max":"FF"}}
Return Error:
{ code: 400,
body: '{"code":"BadRequest","message":"Message: {\\"Errors\\":[\\"The continuation token specified in the request is malformed. Please re-run the query without it and iterate.\\"]}\\r\\nActivityId: 9e04278a-3808-4a59-8e63-dae191ef3519, Request URI: ...."}',
activityId: '9e04278a-3808-4a59-8e63-dae191ef3519' }
So basically I'm loading the page with limit of 2 items. Then for next page I'm sending the continuation token, but I'm getting back the error malformed token.
What am I doing wrong?

Promise Chain doesn't seem to continue

I'm trying to get my promise chain to work in my express post, but can't seem to figure out why it won't work, even though I've done this before.
I added many logs to follow where it stops, and it seems to stop after the validation resolve, does not continue
Promise:
router.post('/auth/token', function (req, res) {
var schema = require('./schema/token.js');
var data = {
username: req.body.username,
password: req.body.password
};
new Promise(function (resolve, reject) {
logger.info(`Validating request..`);
return validator.validate(schema, data);
}).then(function () {
logger.info(`Getting token..`);
return authentication.getToken(data.username, data.password);
}).then(function (result) {
logger.info(`Received token..`);
res.send(result);
}).catch(function (err) {
logger.info(`Unable to receive token..`);
res.send(err);
})
})
Validator.js:
module.exports.validate = function (schema, data) {
return new Promise(function(resolve, reject){
logger.info(`Loading schema..`);
if (!schema) {
logger.info(`Missing schema, rejecting promise..`);
return reject(new Error('Missing schema'));
}
const ajv = new Ajv({ v5: true, allErrors: true });
logger.info(`Compling schema..`);
const validate = ajv.compile(schema);
logger.info(`Validating schema..`);
const valid = validate(data);
if (!valid) {
const errors = validate.errors.map((error) => `${error.dataPath.replace('.', '')}: ${error.message}`);
const err = new Error(errors);
return reject(err);
}
logger.info(`Valid schema.. resolving..`);
return resolve();
})
}
When I run this.. the logs say the following:
info: Validating request..
info: Loading schema..
info: Compling schema..
info: Validating schema..
info: Valid schema.. resolving..
No longer continues, it should continue to the next promise, now if I change the first promise and force a resolve and reject, it'll work but as far as I know, that should not be required as the validate returns a promise and I'm not getting any errors
Any ideas?
Don't create a new promise, use the one from validate; see *** below:
router.post('/auth/token', function (req, res) {
var schema = require('./schema/token.js');
var data = {
username: req.body.username,
password: req.body.password
};
logger.info(`Validating request..`); // ***
validator.validate(schema, data) // ***
.then(function () {
logger.info(`Getting token..`);
return authentication.getToken(data.username, data.password);
}).then(function (result) {
logger.info(`Received token..`);
res.send(result);
}).catch(function (err) {
logger.info(`Unable to receive token..`);
res.send(err);
})
})
The issue is you never resolve the new promise you create. But since there's no good reason to create a new promise when you already have one, the solution is to use the one you have.

Calling async functions recursively

I need to have an async method eg. getWeather called forever with a small delay between the success of previous call and beginning of the next call. I have used a recursive function for the purpose. I am concerned if this can cause a performance hit. Are there any better ways to do this?
var request = require('request');
var Promise = require('bluebird');
var delayTwoSecs = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, 2000);
});
};
var getWeather = function() {
return new Promise(function(resolve, reject) {
request({
method: 'GET',
uri: 'http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139'
}, function(error, response, body) {
if (error) {
reject(error);
} else {
resolve(body)
}
});
});
};
var loopFetching = function() {
getWeather()
.then(function(response) {
console.log(response);
return delayTwoSecs();
}).then(function(response) {
loopFetching();
});
};
loopFetching();
You don't need the delayTwoSecs function, you can use the Promise.delay function.
Instead of getWeather, you can use the bluebird to Promisify all the functions and use the proper function, in this case getAsync, directly.
So, your program becomes like this
var Promise = require('bluebird');
var request = Promise.promisifyAll(require('request'));
var url = 'http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139';
(function loopFetching() {
request.getAsync(url)
// We get the first element from the response array with `.get(0)`
.get(0)
// and the `body` property with `.get("body")`
.get("body")
.then(console.log.bind(console))
.delay(2000)
.then(loopFetching)
.catch(console.err.bind(console));
})();
This is called Immediately Invoking Function Expression.
setInterval() for recurring requests
You're over-complicating it with nested calls. Use setInterval() instead.
var request = require('request');
var Promise = require('bluebird');
var getWeather = function() {
return new Promise(function(resolve, reject) {
request({
method: 'GET',
uri: 'http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139'
}, function(error, response, body) {
if (error) {
reject(error);
} else {
resolve(body)
}
});
});
};
var my_interval = setInterval("getWeather()",2000);

Promise returns early with a for loop

I'm new to Promises so I might be doing something stupid here, but I can't seem to figure it out.
Just so I know I'm on the right path, a bit of information upfront. I have an authenticate method which returns a promise:
APIWrapper.prototype.authenticate = function() {
var self = this;
return new Promise(function(resolve, reject) {
request({
uri: self.httpUri + '/auth/authenticate',
method: 'GET',
headers: {
auth_user: self.user,
auth_pass: self.pass,
auth_appkey: self.appkey
}
}, function(err, res, body) {
if (err) return reject(err);
self.parser.parseXML(body, function(err, result) {
if (err) return reject(err);
if (result.error) { return reject(result.error) }
self.token = result.auth.token[0];
return resolve(result);
});
});
});
};
I chain this with .getDashboards() like this:
wrapper.authenticate().then(function() {
wrapper.getDashboards();
}).then(function(result) {
console.log('result', result);
});
.getDashboards() also returns a promise:
APIWrapper.prototype.getDashboards = function() {
var self = this;
return new Promise(function(resolve, reject) {
request({
url: self.httpUri + '/user/dashboard',
method: 'GET',
headers: {
auth_appkey: self.appkey,
auth_token: self.token
}
}, function(err, res, body) {
if (err) { return reject('Could not connect to the API endpoint'); };
self.parser.parseXML(body, function(err, data) {
var dashboards = [];
if(err) { return reject(err); }
if(data.error) { return reject(data.error); }
for(var i = 0; i < data.Dashboards.Dashboard.length; i++) {
dashboards.push(self.getDashboard(data.Dashboards.Dashboard[i]));
}
// returns early here
resolve(dashboards);
});
});
});
};
With the .getDashboard() method like this at the moment:
APIWrapper.prototype.getDashboard = function(db) {
var dashboard = {};
dashboard.title = db.Title[0];
dashboard.id = db.$.id;
console.log(dashboard);
return dashboard;
};
What happens with this code is that it returns the result before it returns the dashboards. I suspect the resolve() in .getDashboards() doesn't wait for the for loop to finish? Do I need to use promises in the .getDashboard() method as well, or how would I wait for it to finish before resolving my .getDashboards() promise?
Output:
> result undefined
{ title: 'Dashboard 1', id: '3271' }
{ title: 'Dashboard 2', id: '3272' }
{ title: 'Dashboard 3', id: '3273' }
I'm using this Promise implementation at the moment: https://github.com/then/promise
You need to return the promise to have it chained :
wrapper.authenticate().then(function() {
return wrapper.getDashboards();
}).then(function(result) {
console.log('result', result);
});
In your case, it can be simplified as
wrapper.authenticate()
.then(wrapper.getDashboards)
.then(function(result){
console.log('result', result);
});
You also don't seem to handle errors. The then library seems very raw on this point, so you should probably add a second argument :
wrapper.authenticate()
.then(wrapper.getDashboards, onAuthenticateError)
.then(function(result){
console.log('result', result);
}, onDashboardError);

Categories

Resources