undefined var module.exports - javascript

For some reason, I can't get values returned from module.exports function from a separate custom module. I tried many ways from many sources from >10s researched posts. If you want to vote down, please read my bio or if you want to help I will be happy to accept your answer.
// restapi/index.js
module.exports = function gifs() {
giphy.search('Pokemon', function (err, res) {
return res.data[0];
});
}
// main server.js
var readapi = require('restapi')
console.log(readapi.gifs());
// Output:__________________
TypeError: readapi.gifs is not a function

You are exporting a function, not an object with a function and you are using a sync function (console.log) with an async operation.. it won't work.
You need to write it like this:
module.exports = function gifs(cb) {
giphy.search('Pokemon', function (err, res) {
if(err) { cb(err) }
else { cb(null, res.data[0]) }
});
}
----
var readapi = require('restapi')
readapi((err, data) => { console.log({err, data}) })
Remember the difference between:
module.export = {
hello: () => { console.log('world') }
}
// usage: require('./hello').hello()
module.export = () => { console.log('world') }
// usage: require('./hello')()

Try this code
module.exports.gifs = function gifs() {
return new Promise((resolve, reject) => {
giphy.search('Pokemon', function (err, res) {
if (err) reject(err);
else resolve(res.data[0]);
});
});
}
// main server.js
var readapi = require('restapi')
readapi.gifs().then(console.log);

Related

s3.getObject not working from dev environment

This is my code, which works fine if i run it from my local using local aws account , but it doesn't work from my dev environment. S3.getobject api doesnt get executed and code prints the next log skipping the getobject call :
const unzipFromS3 = (key) => {
return new Promise(async (resolve, reject) => {
log.info("inside unzipfroms3");
var zlib = require('zlib');
// let fileName = _.replace(key, 'Root/', '');
let options = {
'Bucket': config.bucketName,
'Key': "Root/" + key,
}
log.info("Key:", options);
await s3.getObject(options).on('error', error => {
log.error(error) }).promise().then((res) => {
yauzl.fromBuffer(res.body, { lazyEntries: true }, function (err, zipfile) {
log.info("Inside Yauzl")
if (err) throw err;
zipfile.readEntry();
zipfile.on("entry", function (entry) {
if (/\/$/.test(entry.fileName)) {
zipfile.readEntry();
} else {
zipfile.openReadStream(entry, function (err, readStream) {
if (err) throw err;
// readStream.pipe(fs.createWriteStream(`result/${entry.fileName}`));
readStream
.pipe(uploadFromStream(s3));
function uploadFromStream(s3) {
log.info("Inside uploadFromStream")
var pass = new Stream.PassThrough();
let options = {
'Bucket': config.bucketName,
'Key': entry.fileName,
}
var params = { ...options, Body: pass };
s3.upload(params, function (err, data) {
log.error(err, data);
});
return pass;
}
readStream.on("end", function () {
zipfile.readEntry();
});
});
}
});
});
});
});
};
In order to use await, i.e. the promised based version of S3.getObject(), you must add the promise() method to your method call as explained in the Using JavaScript Promises chapter of the AWS SDK developer guide. Moreover, there is also an Using async/await chapter that you can look into.
In your case, the code can be modified to something like:
await s3.getObject(options).promise()
.then((res) => {
yauzl.fromBuffer(/* more code */);
});

Why is my callback function not being invoked?

I have a function that gets the contents of a load of files and places them in array. I need that array to be referenced in the function that calls the function. I've got a callback in the calling function but it doesn't get invoked.
Any suggestions?
(for purposes of illustration, I have 2 console log calls on the array I need to get back. The 1st is inside my callback which never gets called, and the second is outside it and unsurprisingly shows an empty array.)
const fs = require('fs');
const path = require('path')
const chai = require('chai');
const chaiExpect = chai.expect;
const logger = require('../../../../app/logger/winston');
const pageFolder = 'app/views/pages';
let pages = [];
fdescribe('html pages', function () {
buildPages(function () {
console.log(pages);
});
console.log(pages)
})
function buildPages() {
filewalker(pageFolder, function (err, pageList) {
if (err) {
throw err;
}
pageList.forEach(function (file) {
if (!fs.file.isDirectory) {
fs.readFileSync(file.substring(39), 'utf8', function (err, pageContents) {
if (err) throw err;
pages.push({ file: file.substring(39), page: pageContents })
})
}
})
});
}
You should pass and call callback to buildPages
const fs = require('fs');
const path = require('path')
const chai = require('chai');
const chaiExpect = chai.expect;
const logger = require('../../../../app/logger/winston');
const pageFolder = 'app/views/pages';
let pages = [];
fdescribe('html pages', function () {
buildPages(function () {
console.log(pages);
});
console.log(pages)
})
function buildPages(cb) {
filewalker(pageFolder, function (err, pageList) {
if (err) {
throw err;
}
pageList.forEach(function (file) {
if (!fs.file.isDirectory) {
fs.readFileSync(file.substring(39), 'utf8', function (err, pageContents) {
if (err) throw err;
pages.push({ file: file.substring(39), page: pageContents })
})
}
})
cb(); // <--- HERE
});
}
You're calling the buildPages function with a function argument even thought you didn't configure it to accept any argument. That's why the function inside doesn't get called.
Simply add a callback function as an argument in buildPages and call that callback function once your done with all the tasks in buildPages
const fs = require('fs');
const path = require('path')
const chai = require('chai');
const chaiExpect = chai.expect;
const logger = require('../../../../app/logger/winston');
const pageFolder = 'app/views/pages';
let pages = [];
fdescribe('html pages', function () {
buildPages(function () {
console.log(pages);
});
console.log(pages)
})
function buildPages(callback) {
filewalker(pageFolder, function (err, pageList) {
if (err) {
throw err;
}
pageList.forEach(function (file) {
if (!fs.file.isDirectory) {
fs.readFileSync(file.substring(39), 'utf8', function (err, pageContents) {
if (err) throw err;
pages.push({ file: file.substring(39), page: pageContents })
})
}
})
callback();
});
}
But i would highly suggest that if you want to get some data from another function. Don't use a global variable as your code will be hard to maintain the more things you add to it, instead pass your data as an argument.
function functionWithResult(callback) {
setTimeout(() => {
var result = [1,2,3,4,5]
callback(result)
}, 1000)
}
functionWithResult(function(result) {
console.log(result)
});

Jest TypeError: function not found

I am trying to run a test with jest, except it cannot find my function. I am exporting multiple functions from one file using module.exports = {}.
Here is my test file:
const queries = ('../config/queries');
test('Check Activation Code. -- checkActivationCode(test#gmail.com, 0123456789) ', () => {
let email = 'test%40gmail.com';
let code = 1234567890;
let result = "";
queries.checkActivationCode(email, code, function(error, result) {
if (error) result = false;
else result = true;
});
expect(result).toBe(true);
});
My file structure is as follows, /config/queries/index.js, I am able to access the functions in my other files just fine.
Here is my queries/index.js file:
module.exports = {
checkActivationCode: function(email, code, callback) {
pool.getConnection(function(error, connection) {
connection.query('SELECT code FROM confirmation WHERE email = ?', [email.toLowerCase()], function(error, results) {
if (error) callback(error);
try {
if (results[0].code === code) {
callback(null, true);
} else {
callback(null, false);
}
} catch (e) {
callback(null, false);
}
});
connection.release();
});
}
}
I forgot to require my queries.
const queries = ('../config/queries');
to
const queries = require('../config/queries');
Simple typo. Thanks #BenceGedai for catching that.

node separating out mongo queries

I'm looking at separating out my mongo db queries into a separate js file to help with reusing the code, something in the format below (this doesn't work). Any ideas how I could do this?
queries.js
var Merchants = require('../models/Merchants');
var query = {
returnMerchantIDs: function () {
var results = Merchants.find(function(err, merchants){
if (err) return console.error(err);
return merchants;
})
return results;
}
module.exports = query;
routes.js
var queries = require('../config/queries');
app.get('/queries', function (req, res) {
res.send(queries.returnMerchantIDs());
});
Your 'return merchants' is actually returning from the callback and not from the returnMerchantIDs function. That is the reason this is not working. There are 2 ways you could go about doing this.
Have returnMerchantIDs accept a callback like so
var query = {
returnMerchantIDs: function (callback) {
var results = Merchants.find(function(err, merchants){
if (err) return console.error(err);
callback(merchants);
})
return results;
}
and this is how you would call this
app.get('/queries', function (req, res) {
queries.returnMerchantIDs(function(merchants) {
res.send(merchants);
}));
});
Or return the promise from mongoose to the caller and exec there passing the callback
var query = {
returnMerchantIDs: function () {
var results = Merchants.find();
return results;
}
}
app.get('/queries', function (req, res) {
queries.returnMerchantIDs().exec(function(err, merchants)) {
if (err) res.send(err) else res.send(merchants);
}

Async-WaterFall not working as expected

waterfall function with two calls but the second on is not waiting for the first one to completely finish. The first one has a mongodb.find() call in it.
Here is the async-waterfall function
app.get("/news", function(req, res) {
async.waterfall([
function (callback) {
var blogs = tendigiEngine.getAllBlogs(callback);
callback(null, blogs);
},
function (blogs, callback) {
var array = tendigiEngine.seperateBlogs(blogs, callback);
callback(null, array );
}
], function (err, result) {
// result now equals 'done'
console.log("done");
console.log(result);
});
});
Here are the two functions being called:
getAllBlogs():
exports.getAllBlogs = function() {
Blog.find(function(err, theBlogs){
if(!err) {
return theBlogs;
}
else {
throw err;
}
});
}
seperateBlogs():
exports.seperateBlogs = function(blogs) {
if(blogs.length === 0 ) {
return 0;
}
else {
blogs.reverse();
var blog = blogs[0];
blogs.shift();
var finArray = [blog, blogs];
return finArray;
}
console.log("asdf");
}
It is important that seperateBlogs won't be called before getAllBlogs() has returned theBlogs, but it is being called before the value is returned. I used Async_Waterfall to avoid this problem but it keeps recurring, which means I am using it wrong. What am I doing wrong here and how can I fix it?
Thanks!
Your exported functions are missing the callback parameters:
exports.getAllBlogs = function(cb) {
Blog.find(cb);
};
exports.seperateBlogs = function(blogs, cb) {
if (blogs.length === 0 )
return cb(null, blogs);
blogs.reverse();
var blog = blogs[0];
blogs.shift();
cb(null, [blog, blogs]);
}
Then your main code can be simplified as well:
async.waterfall([
tendigiEngine.getAllBlogs,
tendigiEngine.seperateBlogs
], function (err, result) {
// result now equals 'done'
console.log("done");
console.log(result);
});

Categories

Resources