Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting error CreateListFromArrayLike called on non-object when trying to use .apply()

Tags:

javascript

I've created a simple little route parsing function so that I can keep my code clean and easily maintainable, this is the little function that gets ran when the app starts up and parses the config.json file and binds the appropriate methods and request paths:

const fs = require('fs');
const path = require('path');
module.exports = function(app, root) {
  fs.readdirSync(root).forEach((file) => {
    let dir = path.resolve(root, file);
    let stats = fs.lstatSync(dir);
    if (stats.isDirectory()) {
      let conf = require(dir + '/config.json');
      conf.name = file;
      conf.directory = dir;
      if (conf.routes) route(app, conf);
    }
  })
}

function route(app, conf) {
  let mod = require(conf.directory);

  for (let key in conf.routes) {
    let prop = conf.routes[key];
    let method = key.split(' ')[0];
    let path = key.split(' ')[1];

    let fn = mod[prop];
    if (!fn) throw new Error(conf.name + ': exports.' + prop + ' is not defined');
    if (Array.isArray(fn)) {
      app[method.toLowerCase()].apply(this, path, fn);
    } else {
      app[method.toLowerCase()](path, fn);
    }
  }
}

The problem I have is some times I need to pass in multiple arguments to an express router, e.g. in the case of using passport something like this:

exports.authSteam = [
  passport.authenticate('facebook', { failureRedirect: '/' }),
  function(req, res) {
    res.redirect("/");
  }
];

So I figure I can just pass them as an array, and then parse them into the router appropriately, my config for example looks like this:

{
  "name": "Routes for the authentication",
  "description": "Handles the authentication",
  "routes": {
    "GET /auth/facebook": "authFacebook",
    "GET /auth/facebook/return": "authFacebookReturn"
  }
}

The only problem is I'm getting this error:

     app[method.toLowerCase()].apply(this, path, fn);
                                ^

TypeError: CreateListFromArrayLike called on non-object

if I console.log(fn) I see [ [Function: authenticate], [Function] ]

I'm not exactly sure what I am doing wrong, any information would be great thanks.

like image 599
Datsik Avatar asked Dec 28 '16 01:12

Datsik


2 Answers

You need to send the params as an array, like this:

app[method.toLowerCase()].apply(this, [path, fn]);

If you want to send an arguments list you need to use call:

app[method.toLowerCase()].call(this, path, fn);

Source: call, apply

like image 106
Martin Mendez Avatar answered Oct 31 '22 13:10

Martin Mendez


Fixed it by changing:

eval.apply(this, 'p1', 'p2')

to:

eval.apply(this, ['p1', 'p2'])

like image 33
yaya Avatar answered Oct 31 '22 15:10

yaya