29

I'm trying to promisify a mysql function but when I run it the console shows this error util.Promisify is not a function. This is my code:

var util=   require('util');
var mysql=          require('mysql');

var conection=mysql.createConnection({           
    host:'localhost',                   
    user:'root',                        
    password:'616897',               
    database:'proyect'                    
 });
  
  var query = util.promisify(conection.query);
  
  query(data.valida_user).then((rows)=>{
 console.log(rows);
}).catch((error)=>{
 console.log(error);
})

The same error if var query = util.promisify(mysql.query);

I´m new programming but I'm trying to learn.

JEllery
  • 304
  • 2
  • 13
Eleazar Ortega
  • 509
  • 2
  • 7
  • 17
  • and add the function with `npm install util`... but i have de version v6.11.2 – Eleazar Ortega Sep 28 '17 at 19:29
  • You could also use [`mysql2`](https://github.com/sidorares/node-mysql2), which is faster, has the same API as `mysql`, and supports promises out of the box. – robertklep Sep 29 '17 at 14:00

10 Answers10

36

util.promisify is a part of Node 8.X version. But you can still have a polyfill for the older version of Node.

A polyfill is available to take care of the older version of node servers you’ll be running your application on. It can be installed via npm in the following manner:

npm install util.promisify

Now you can patch module utl on older versions of Node

const util = require('util');
require('util.promisify').shim();

const fs = require('fs');
const readFileAsync = util.promisify(fs.readFile);
WEBjuju
  • 5,797
  • 4
  • 27
  • 36
zubair1024
  • 843
  • 8
  • 24
8

Unless you're using Node.js 8.x this function won't be defined, that's when it was added to the core Utilities library.

As util is a core Node.js library, you shouldn't have to install it. If you're using Node.js 6.x then use a library like Bluebird which has a promisify function.

tadman
  • 208,517
  • 23
  • 234
  • 262
6

Other people have spoken to the solution, but here is another source of this error:

There's a NPM package es6-promisify that can also give the error message TypeError: promisify is not a function. (That's why I got to this question.)

  • Version 5.0.0 of es6-promisifiy needed const promisify = require("es6-promisify"); then you'd use result = promisify( ... );

  • Version 6.0.0 had a change of API, and the declaration changed to const { promisify } = require("es6-promisify");

richb-hanover
  • 1,015
  • 2
  • 12
  • 23
4

You can promise it by yourself if you want: const promisify = f => (...args) => new Promise((a,b)=>f(...args, (err, res) => err ? b(err) : a(res)));

Shl
  • 3,130
  • 1
  • 17
  • 16
  • 1
    I like this I only do not understand it. Could you provide a link which will explain that and how this works? I have troubles with understanding const promisify = ... => ... => ... => ... – user1325696 Mar 24 '18 at 16:41
  • const is var which can't be changed. – Shl Mar 25 '18 at 20:54
  • 1
    func(...[1,2]) means like func(1,2), ...args means multiple arguments. x => x*x means for each x return x*x. It's a function. So, for each f return a function that will get ...args. for that function create new promise. for that promise which has resolve (a) and reject (b) option return the result of f (some function) triggered with the ...args and also a function (callback) but in the callback call resolve or reject according to the error argument existence (should always be first argument). So, eventually you get a Promised function. – Shl Mar 25 '18 at 21:04
  • Shl, I understand what => does, in the next code example "const square = x => x*x;", But I still not clear const promisify = f => (...args) => .... How do I read those 2 sequences of "=>". The other thing is not clear to me as what about bind? Will this promisify correctly work with this in the f function? – user1325696 Mar 26 '18 at 00:57
  • Shl, thanks for your help I found an answer here https://stackoverflow.com/questions/32782922/what-do-multiple-arrow-functions-mean-in-javascript and here http://babeljs.io/repl/#?babili=false&browsers=&build=&builtIns=false&code_lz=MYewdgzgLgBADgJxAWwJYVQMwJ4wLwyb4B8MAFAHRUCGCA5hAJQkxgCmA7jAApJoRsyZagBoARozzFMlGvQgjybBAkUI2TFsoQwA_DDFltzAFwxqZdU0aMA3EA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=true&fileSize=false&lineWrap=false&presets=latest%2Creact%2Cstage-2&prettier=false&targets=&version=6.26.0&envVersion= – user1325696 Mar 26 '18 at 01:41
4

Util is included from Node 8.x on so if you can update node I'd do that.

Seph Cordovano
  • 1,824
  • 1
  • 16
  • 19
3

The following example should work for you:

async () => {
  const connection = await (util.promisify(pool.getConnection).bind(pool))();

  const fn2 = util.promisify(connection.query).bind(connection);
  const rows = await fn2('SELECT col1, col2 FROM Users WHERE email = ?', [email]);

  connection.release();

  return rows;
}

This example uses the standard MySQL module for Node.js. And the util.promisify is the built-in utility of Node.js. Node 8 is used.

The code is wrapped into an async function. Within it on the first line the callback function ‘pool.getConnection’ is converted into promises and called instantly with the additional ‘await’ statement. This creates a sequence of the async function and returns a value (a connection) instead of a function or promises. The next line does the same for the ‘conection.query’, but splits the code into two statements for the sake of simplicity. Finally the function returns the result of the query like any synchronous function.

user2080851
  • 718
  • 6
  • 7
1

If you have a webpack/babel setup, you can use babel-plugin-transform-util-promisify. It allows you to use util.promisify in node versions < 8. Also very useful if you are targeting node versions >= 8 but want to keep backward compatibility for lower versions.

The plugin transforms code written in the following two formats:

const { promisify } = require('util');

and

import { promisify } from 'util';

You would need to setup the plugin in your .babelrc:

{
  "plugins": [
    "transform-util-promisify"
    ],
    "presets": [
      ["env", {
        "targets": {
          "node": "current"
        }
      }]
    ]
}

The plugin transforms import and require to a function declaration for node versions < 8. It automatically detects version >= 8 and uses native util.promisify in those cases.

Disclosure I'm author and maintainer of babel-plugin-transform-util-promisify

Keyvan
  • 813
  • 9
  • 19
0

Share my working example:

I use this Promisified MySQL middleware for Node.js

here is my database.js

var mysql = require('mysql'); 

// node -v must > 8.x 
var util = require('util');


//  !!!!! for node version < 8.x only  !!!!!
// npm install util.promisify
//require('util.promisify').shim();
// -v < 8.x  has problem with async await so upgrade -v to v9.6.1 for this to work. 



// connection pool https://github.com/mysqljs/mysql   [1]
var pool = mysql.createPool({
  connectionLimit : process.env.mysql_connection_pool_Limit, // default:10
  host     : process.env.mysql_host,
  user     : process.env.mysql_user,
  password : process.env.mysql_password,
  database : process.env.mysql_database
})


// Ping database to check for common exception errors.
pool.getConnection((err, connection) => {
if (err) {
    if (err.code === 'PROTOCOL_CONNECTION_LOST') {
        console.error('Database connection was closed.')
    }
    if (err.code === 'ER_CON_COUNT_ERROR') {
        console.error('Database has too many connections.')
    }
    if (err.code === 'ECONNREFUSED') {
        console.error('Database connection was refused.')
    }
}

if (connection) connection.release()

 return
 })

// Promisify for Node.js async/await.
 pool.query = util.promisify(pool.query)



 module.exports = pool

You must upgrade node -v > 8.x

you must use async function to be able to use await.

example:

   var pool = require('./database')

  // node -v must > 8.x, --> async / await  
  router.get('/:template', async function(req, res, next) 
  {
      ...
    try {
         var _sql_rest_url = 'SELECT * FROM arcgis_viewer.rest_url WHERE id='+ _url_id;
         var rows = await pool.query(_sql_rest_url)

         _url  = rows[0].rest_url // first record, property name is 'rest_url'
         if (_center_lat   == null) {_center_lat = rows[0].center_lat  }
         if (_center_long  == null) {_center_long= rows[0].center_long }
         if (_center_zoom  == null) {_center_zoom= rows[0].center_zoom }          
         _place = rows[0].place


       } catch(err) {
                        throw new Error(err)
       }
hoogw
  • 4,982
  • 1
  • 37
  • 33
0

My problem was that I had not installed util in the first place.

So, npm i util solved my issue

-1

Here is an implementation of promisify:

var promisify = function(fn) {
  return function(){
    var args = [].slice.apply(arguments);
    return new Promise(
      function(resolve,reject){
        fn.apply(
          null,
          args.concat([
            function(){
              var results = [].slice.apply(arguments);
              (results[0])//first argument of callback is error
                ? reject(results[0])//reject with error
                : resolve(results.slice(1,results.length))//resolve with result(s)
            }
          ])
        )
      }
    );
  }
};

//some object that has async functions using callbacks 
// and using 'this' as invoking object
var callbackApi = {
  name:"callback api",
  age:22,
  asyncFunction:function(arg1,arg2,callback){
    setTimeout(
      function(){callback(null,arg1,arg2,this.name,this.age);}.bind(this),
      10
    )
  }
}

//my object that will use the api functions with promisify
//  and using 'this' as invoking object
var myObject = {
  connection:"connection",
  doSomething:function(arg){
    var asyncFnAsPromise = 
      //make sure to bind asyncFunction to callbackApi
      promisify(callbackApi.asyncFunction.bind(callbackApi));
    //return promise created with result promisified callback api
    return asyncFnAsPromise(this.connection,arg)
  }
}

myObject.doSomething(44)
.then(
  resolve=>console.log("resolve:",resolve)
);
HMR
  • 37,593
  • 24
  • 91
  • 160