Firebase cloud functions says Unreachable and each then() should return a value or throw promise/always-return - node.js

Javascript code for Firebase cloud functions giving errors which written for push notifications
index.js
'use strict'
//Install functions and admin sdks'
const functions = require('firebase-functions');
const admin =require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/notifications/{user_id}/{notification_id}').onWrite((change, context) => {
//onwrite will run if data changed
const user_id = context.params.user_id;
const notification = context.params.notification;
if (context.params === null) {
return console.log("Notification Has Been Deleted");
}
let token_id = null;
const deviceToken = admin.database.ref(`/Users/${user_id}/device_token`).once('value');
return deviceToken.then(result => {
token_id = result.val();
const payload = {
notification:{
title:"Friend Request",
body:"You have recieved a new friend request",
icon:"default"
}
};
});
return admin.messaging().sendToDevice(token_id, payload).then(response =>{
console.log('This is the notify feature');
}).catch(err => {
console.log('Error getting documents', err);
});
});
When run firebase deploy command it is getting error as follows. I would be greateful if anyone can support.
Error
error Each then() should return a value or throw promise/always-return
error Unreachable code no-unreachable
error Each then() should return a value or throw promise/always-return
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! functions# lint: `eslint .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the functions# lint script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

The error is saying that you should return a value from the callback passed to any then() method. You have two then() methods in your code. If you have nothing to send to the next item of work in the promise chain, just return null at the end of the function.
There is an even bigger problem in your code, though. You have two return statements at the top level of your function, one right after the other. This is almost certainly going to cause another error, or at least fail to do what you expect. (You must return only one promise that resolves when all the work is complete.)

Related

Node.js unit test spawn command to view npm package details

I'm creating a function that gets the tarball uri of a package name. It works, but the problem is how can automate tests for it? Do I somehow mock the command line or somehow mock the npm registry? I'm not sure what the protocol is that npm uses.
const spawn = require('child_process').spawn;
let url = spawn('npm', ['view', 'express', 'dist.tarball']);
url.stdout.on('data', data => {
console.log(data.toString());
});
url.stderr.on('data', data => {
console.log(data.toString());
});
//should be 0 if all OK
url.on('close', code => {
if (code) {
console.log('process failed');
}
});
Ok, used a combination of rewire and mock-spawn.

Node scandir permission denied

I am programming a Node js application which will be running on Raspberry PI 3. I am making a functionallity that will scan the /media/pi folder and then scan the folders inside that folder to find config.json
I have this two functions which do that:
function findUSBFolders() {
return fs.readdirSync(mediaFolder);
}
function findConfigFiles(p) {
ret = [];
files = fs.readdirSync(p);
for(var i in files) {
if(files[i].startsWith('config')) {
ret.push(path.join(p, files[i]));
}
}
return ret;
}
On one raspberry I don't get any errors but on the other I get this:
fs.js:912
return binding.readdir(pathModule._makeLong(path), options.encoding);
^
Error: EACCES: permission denied, scandir '/media/pi/D03E-191B'
at Object.fs.readdirSync (fs.js:912:18)
at findConfigFiles (/home/pi/seatcontroller/src/waitConfig.js:78:13)
at findConfigs (/home/pi/seatcontroller/src/waitConfig.js:61:21)
at Timeout._onTimeout (/home/pi/seatcontroller/src/waitConfig.js:35:15)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)
these are the permissions for /media/pi:
pi#raspberrypi:~ $ ls -l /media/pi
total 4
drwx------ 4 pi pi 4096 Jan 1 1970 D03E-191B
I also tried to run sudo with node server.js but it acts strange, it seems that it gets stuck when I run it with sudo.
Let me know if you need some more code.
What could be the problem?
EDIT
When I do sudo node server.js my chromium browser doesn't get launched. In my code I do this to accomplish that:
server.start((err) => {
if (err) {
throw err;
}
server.log('info', `Server running at: ${server.info.uri}`);
chromium.start();
main.start(require('./src/apiInvoker'), require('./src/qr'));
unclutter.start();
});
where chromium is this module:
const spawn = require('child_process').spawn;
module.exports = {
start: function() {
const chromium = spawn('chromium-browser', ['--kiosk', 'http://localhost:3003']);
}
};
It is launched when I run it without sudo...

Do an operation interactively and it works. Do the same operations programmatically and it fails. Redis, heroku, node

Here's my interactive session. It works great.
ec2-54-83-60-31.compute-1.amazonaws.com:11729> keys *
1) testkey
ec2-54-83-60-31.compute-1.amazonaws.com:11729> flushall
OK
ec2-54-83-60-31.compute-1.amazonaws.com:11729> keys *
ec2-54-83-60-31.compute-1.amazonaws.com:11729> watch testkey
OK
ec2-54-83-60-31.compute-1.amazonaws.com:11729> multi
OK
ec2-54-83-60-31.compute-1.amazonaws.com:11729> set testkey testvalue
QUEUED
ec2-54-83-60-31.compute-1.amazonaws.com:11729> exec
1) OK
ec2-54-83-60-31.compute-1.amazonaws.com:11729> keys *
1) testkey
ec2-54-83-60-31.compute-1.amazonaws.com:11729> get testkey
testvalue
ec2-54-83-60-31.compute-1.amazonaws.com:11729>
Here's the my code, and how executing it looks.
var redis = require('redis');
var rdsclt = redis.createClient(process.env.REDIS_URL);
console.log('Before test block.');
console.log('rdsclt.flushall();');
rdsclt.flushall();
console.log('rdsclt.watch(\'testkey\');');
rdsclt.watch('testkey');
console.log('rdsclt.multi();');
rdsclt.multi();
console.log('rdsclt.set(\'testkey\', \'testvalue\');');
rdsclt.set('testkey', 'testvalue');
console.log('rdsclt.exec( (error, results) => {');
rdsclt.exec( (error, results) => {
console.log('Inside test block exec callback.');
console.log('error =', JSON.stringify(error) );
console.log('results =', JSON.stringify(results) );
});
console.log('After test block.');
return 0; // Hopefully, indicates success, in Unix.
2016-11-07T19:39:20.038712+00:00 heroku[web.1]: Starting process with command `npm start`
2016-11-07T19:39:22.685896+00:00 app[web.1]:
2016-11-07T19:39:22.685912+00:00 app[web.1]: > cubsredistest#1.0.0 start /app
2016-11-07T19:39:22.685913+00:00 app[web.1]: > node main.js
2016-11-07T19:39:22.685914+00:00 app[web.1]:
2016-11-07T19:39:22.918869+00:00 app[web.1]: Before test block.
2016-11-07T19:39:22.919519+00:00 app[web.1]: rdsclt.flushall();
2016-11-07T19:39:22.920435+00:00 app[web.1]: rdsclt.watch('testkey');
2016-11-07T19:39:22.920662+00:00 app[web.1]: rdsclt.multi();
2016-11-07T19:39:22.920903+00:00 app[web.1]: rdsclt.set('testkey', 'testvalue');
2016-11-07T19:39:22.920959+00:00 app[web.1]: rdsclt.exec( (error, results) => {
2016-11-07T19:39:22.921021+00:00 app[web.1]: After test block.
2016-11-07T19:39:22.937915+00:00 app[web.1]: Inside test block exec callback.
2016-11-07T19:39:22.938011+00:00 app[web.1]: error = {"command":"EXEC","code":"ERR"}
2016-11-07T19:39:22.938287+00:00 app[web.1]: results = undefined
2016-11-07T19:39:00+00:00 app[heroku-redis]: source=REDIS sample#active-connections=1 sample#load-avg-1m=0.09 sample#load-avg-5m=0.13 sample#load-avg-15m=0.1 sample#read-iops=0 sample#write-iops=0 sample#memory-total=15664468.0kB sample#memory-free=13536884.0kB sample#memory-cached=694560kB sample#memory-redis=289016bytes sample#hit-rate=1 sample#evicted-keys=0
I would have said these two should yield the same results, and yet they don't. I'm using the redis client that is installed using npm install redis . I know there are other clients.
Does anybody know what's going on?
I changed the node client from node_redis to ioredis.
Changed from npm install redis to npm install ioredis.
Now the error message is more informative.
2016-11-07T20:28:02.704282+00:00 app[web.1]: Inside test block exec callback.
2016-11-07T20:28:02.704615+00:00 app[web.1]: error = {"name":"ReplyError","message":"ERR EXEC without MULTI","command":{"name":"exec","args":[]}}
2016-11-07T20:28:02.704620+00:00 app[web.1]: results = undefined
2016-11-07T20:27:43+00:00 app[heroku-redis]: source=REDIS sample#active-connecti
Still haven't solved the problem.
Arghh! An example from node_redis' tests is:
it('does not execute transaction if watched key was modified prior to execution', function (done) {
client.WATCH(watched);
client.incr(watched);
var multi = client.multi();
multi.incr(watched);
multi.exec(helper.isNull(done));
});
What I was doing is this:
it('does not execute transaction if watched key was modified prior to execution', function (done) {
client.WATCH(watched);
client.incr(watched);
client.multi();
client.incr(watched);
client.exec(helper.isNull(done));
});
I'll leave this here. Maybe it'll help the next person.

Error in fs.readFileSync() in nodejs

I am calling a sync call using require('fs'); in nodejs
var folder_path = '/home/abc';
var myfiles = ['a.png','b.png'];
_.each(myfiles, function(name){
var data = fs.readFileSync(folder_path+'/'+name);
if(data){
// Some operation
}
});
while calling that function i'm getting Error: EISDIR, illegal operation on a directory
fs.js:488
var r = binding.read(fd, buffer, offset, length, position);
^
Error: EISDIR, illegal operation on a directory
at Object.fs.readSync (fs.js:488:19)
at Object.fs.readFileSync (fs.js:322:28)
at /home/coader/dev/api/controllers/MyController.js:66:30
at Function.forEach ( /home/coader/dev/node_modules/sails/node_modules/lodash/dist/lodash.js:3298:15)
at /home/coader/dev/api/controllers/MyController.js:41:11
at Object.oncomplete (fs.js:108:15)
error: Forever detected script exited with code: 8
Details
$ node -v
v0.10.37
$ nodejs -v
v0.10.37
$ npm -v
1.4.28
Any answer will be appreciable.
Thanks
I think you might have to settle for "myfiles.forEach(function(name)"
var folder_path = '/home/abc';
var myfiles = ['a.png','b.png'];
myfiles.forEach(function(name){
var data = fs.readFileSync(folder_path+'/'+name);
if(data){
// Some operation
}
});

Node.js throw new Error('Can\'t set headers after they are sent.');

This the error:
{}
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.'); Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.setWriteHeadHeaders (D:\xampp\htdocs\wisaa\node_express\node_modules\morgan\node_modules\on-headers\index.js:80:19)
at ServerResponse.writeHead (D:\xampp\htdocs\wisaa\node_express\node_modules\morgan\node_modules\on-headers\index.js:39:36)
at ServerResponse.writeHeader (_http_server.js:233:18)
at Object.queue.drain (D:\xampp\htdocs\wisaa\node_express\routes\index.js:52:13)
at D:\xampp\htdocs\wisaa\node_express\node_modules\async\lib\async.js:871:23
at D:\xampp\htdocs\wisaa\node_express\node_modules\async\lib\async.js:44:16
at D:\xampp\htdocs\wisaa\node_express\routes\index.js:43:21
at Socket.<anonymous> (D:\xampp\htdocs\wisaa\node_express\node_modules\email-verify\index.js:145:13)
at Socket.emit (events.js:129:20)
npm ERR! Windows_NT 6.2.9200 npm ERR! argv "C:\\Program Files (x86)\\nodejs\\\\node.exe" "C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "start" npm ERR! node v0.12.5 npm ERR! npm v2.11.2 npm ERR! code ELIFECYCLE npm ERR! node_express#0.0.0 start: `node ./bin/www` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the node_express#0.0.0 start script 'node ./bin/www'. npm ERR! This is most likely a problem with the node_express package, npm ERR! not with npm itself. npm ERR! Tell the author that this fails on your system: npm ERR! node ./bin/www npm ERR! You can get their info via: npm ERR! npm owner ls node_express npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request: npm ERR! D:\xampp\htdocs\wisaa\node_express\npm-debug.log`
This is my code:
var express = require('express');
var router = express.Router();
var _ = require('underscore');
var fs = require('fs'),
async = require('async'),
verifier = require('email-verify');
/* GET home page. */
router.post('/', function(req, res, next) {
var emails = req.body.emails;
emails = emails.split(',');
var queue = async.queue(function(task, callback) {
task(callback);
}, 100);
_.each(emails, function(e, i) {
queue.push(function(cb) {
var done = false;
verifier.verify(e, function(err, info) {
if (err) {
//console.log(err);
// fauile
emails.splice(emails.indexOf(e), 1);
var score = "Your email is nor valid neither exist";
} else {
if (info.success) {
// success
res.json({
'message': emails
});
} else {
emails.splice(emails.indexOf(e), 1);
}
}
if (!done) {
done = true;
cb(null, true);
console.log('something bad happened!');
}
});
});
});
queue.drain = function() {
console.log(arguments);
res.writeHeader(200, {
'content-Type': 'text/plain'
});
res.send(JSON.stringify(emails));
res.end();
}
});
module.exports = router;
It looks like you'll be calling res.json() one or more times per request. That's not allowed because it sends the response (and headers hence error). There should be only one response per request.
When you do _.each, you're making a loop. In this case, you're adding a bunch of functions to a queue. When each function in that queue is processed you're calling res.json(). res.json() sends a response which is something you can only do once, not multiple times.
You can do any kind of processing of the emails that you need in this queue if you need to but don't actually send it with res.json until the callback is called, so in drain.
As already pointed out by #Matt Harrison , i am trying to add little description to it only.
It looks like,
res.json({
'message':emails
});
is getting called first which is responsible for sending the json response to the client, hence completing the request-response cycle.
So, after this point any attempt on res object is immaterial as response has already been sent.
Since you are getting following exception
new Error('Can\'t set headers after they are sent.');
So, most probably, queue.drain() is called, which is setting the header. At this point you are getting the error.
try:
verifier.verify(e, function(err, info) {
if (err) {
//Return the error itself
return res.send(err);
//The rest of your code here
...
}else{...}
you need to add the 'return' so that you don't reply twice. In a nutshell, Your code needs to have a return or an else so when there's an error you don't execute both code paths. That's where the error is coming from in my opinion.
Hope this helps.!

Resources