McB
McB

Reputation: 1232

Best way to set up JSForce Connection middleware in Node/Express App

I've got a simple node App that uses JSForce to connect to Salesforce to push/query our Salesforce Account. I'm using a username/password authentication rather than OAuth.

It's working fine now, but it's still in dev, and I'm noticing my page loads are very slow, likely because on each load I'm establishing a connection, logging in, and appending the connection to req via middleware.

router.use('/*time*',
  sftools.conn, // Create connection to Salesforce
  sftools.login, // Login to SalesForce
  sftools.picklist //populate res.locals.roles with SalesForce Roles
)

A sample of the middleware code:

const jsforce = require('jsforce')

exports.conn = (req, res, next) => {
  req.conn = new jsforce.Connection({
    loginUrl: process.env.SF_LOGINURL
  })
  next()
}

exports.login = (req, res, next) => {
  req.conn.login(process.env.SF_USER, process.env.SF_PASS, (err) => {
    if(err) return next(err)
    next()
  })
}

Again, this works, but I think I should be setting up the connection and logging in globally, I'm just not sure how exactly to do this and where it should go in my app. Even if I do this, should I still assign the conn to the request, or just access it directly? First Node app... Any ideas are appreciated.

Upvotes: 0

Views: 1978

Answers (1)

croeck
croeck

Reputation: 766

If you want your connection to stay open even after the request has been processed, you should extract your connection handling to a dedicated module / file.

Calling 'require' from within node is going to always return the same instance:

(...) every call to require('foo') will get exactly the same object returned, if it would resolve to the same file. Multiple calls to require('foo') may not cause the module code to be executed multiple times. (...)

Please check the nodejs documentation for further information:

With this in mind, you could create a dedicated handler file...

// sfConnectionHandler.js
const jsforce = require('jsforce')

let currentConnection

function createConnection() {
    currentConnection = new jsforce.Connection({ loginUrl: process.env.SF_LOGINURL })
    currentConnection.login(process.env.SF_USER, process.env.SF_PASS, (err) => {
        // your error handling
    })
    // use promises, call next(), ...
}

function connection() {
    // assert whatever you feel is necessary (is alive, logged in, ...)
    if(!currentConnection) {
        createConnection();
    }
    return currentConnection;
}

module.exports = connection;

... and then require this file where ever you want to use your connection.

const sfConnectionHandler = require('./sfConnectionHandler');
sfConnectionHandler.connection.query('...');

The connection must not be attached to every request. I can't think of any advantages, as long as there are no special connections.

Upvotes: 2

Related Questions