sqlanywhere / node-sqlanywhere

SAP SQL Anywhere Database Client for Node
Apache License 2.0
38 stars 36 forks source link

Wrapping execution inside a promise freezes #27

Closed martvaha closed 5 years ago

martvaha commented 6 years ago

I'm having trouble wrapping connect and exec methods inside a promise. For some reason, the promise is only resolved after the request to the backend has been canceled in the browser.

Environment: OS: MacOS 10.13.3 / Ubuntu 10.13.3 NodeJS: 8.9.4 / 9.5.0

Steps to reproduce:

npm install express sqlanywhere

const express = require('express');
const sqlanywhere = require('sqlanywhere');

const app = express();

app.get('/', (req, res) => {
  const conn = sqlanywhere.createConnection();
  const conn_params = {
    Host: '****',
    UserId: '****',
    Password: '****'
  };
  const promise = new Promise((resolve, reject) => {
    conn.connect(conn_params, err => {
      if (err) reject(err);
      conn.exec('select 1 as test', (err, result) => {
        if (err) reject(err);
        console.log(result);
        resolve(result);
      });
    });
  });
  promise.then(data => {
    console.log('inside promise.then');
    res.json(data);
  })
});

app.listen(3000);

process.on('SIGINT', function() {
  process.exit();
});

node app.js

Open http://localhost:3000/. The result of exec is logged to the console but the response is not sent back to the browser. Also the console.log inside promise.then is logged only after the request has been canceled in the browser.

What am I missing?

martvaha commented 6 years ago

@gperrow-SAP Any ideas?

gperrow-SAP commented 6 years ago

I looked into this on Friday and wasn't able to determine the problem. If I remove the express stuff and just use the sqlanywhere module with a promise, it works as expected. If I remove sqlanywhere and just use express with a promise, it works properly as well. It's the combination of the two that causes the problem but I haven't been able to determine why yet. I'm still investigating.

martvaha commented 6 years ago

Thank you so much for looking into this. I just managed to get the promise to resolve by wrapping the callback function inside a Nan::Callback (had to introduce nan dependency). This is not a clean solution and I have no clue why this works, but maybe it helps in finding a proper solution. The changes I made can be seen here: https://github.com/martvaha/node-sqlanywhere/commit/495c4385ca0c77156ade6f7addbec348796ac05b

thegnuu commented 6 years ago

I run into the same issue today using apollo-server 2.0.0-rc.6. Is there now a proper solution or do we need to use martvahas workaround?

martvaha commented 6 years ago

I'm still using the workaround, but it should work fine for now.

thegnuu commented 6 years ago

Thank you @martvaha, I forked it and implemented your fix. Until now, everything seems to be working fine!

CedricSch commented 5 years ago

Is their another solution in the meanwhile? When I wrap the resolve/reject object into a setImmediate() it works fine as long as the request load isnt that high (otherwise i get some weird behaviour)

i.e

 return new Promise( (resolve, reject) => {
          console.log("In OpenConnection")
        connection.connect(params, (err) => {
            (err) ? setImmediate( () => { console.log(`1.) Before Reject OpenConnection, requestID: ${req}`); reject(err) }):
                    setImmediate( () => { console.log(`1.) Before Resolve OpenConnection, requestID: ${req}`); resolve(); });
        })
      })
thegnuu commented 5 years ago

As far as I know there is still no fix for this issue until now.

gperrow-SAP commented 5 years ago

This should be fixed with version 1.0.24.