0

How can I wrap an existing node.js api (an npm module: PythonShell) into a promise to make it synchronous. Here is my attempt (based on other similar questions):

    new Promise(function(resolve, reject) {

        PythonShell.run('./script.py', (err, results) => {
              resolve(results); // no errors in this case
        })

    }).then(r => {
        return r;
    });

All inside a normal function. This returns a promise for some reason, I expect it to return the value of r.

robert
  • 731
  • 1
  • 5
  • 22

2 Answers2

2

It returns a promise because this is a Promise. You need to wait for the Promise to resolve by putting your code in the then or by using async/await. A Promise does not make your code synchronous.

For example

function run() {
  return new Promise((resolve, reject) => {
    PythonShell.run('./script.py', (err, results) => {
      if (err) {
        return reject(err)
      }
      return resolve(results);
    })
  })
}

async function main() {
  const results1 = await run();
  // Or
  run().then((results2) => {
    // Do something with results2 here, not outside out this block
  })
}

main()

ThomasThiebaud
  • 11,331
  • 6
  • 54
  • 77
  • Thanks for the explanation. I thought adding then() within the original method would wait for the promise to be resolved just like calling then() after returning a promise. I'm still not quite sure why my code doesn't work though, why doesn't ".then(r => { return r; });" do the same as calling that outside the method – robert Oct 01 '19 at 07:08
  • @robert `.then` wraps the returned value into a promise and returns it to parent promise then you need to return the parent promise upto the complete hierarchy. also rather using `return new Promise(...) for wrapping` you should use [util.promisify](https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original)`(PythonShell.run)` – AZ_ Oct 01 '19 at 07:12
0

Create an async function/Promise to get the result from your script:

const getValue = () => {
    return new Promise((resolve, reject) => {
        PythonShell.run('./script.py', null, (err, results) => {
            if(err) reject(err);
            else resolve(results);
        });
    });
}

and the you can call it like:

getValue()
.then((r) => {
    console.log("Result is => ", r);
    // Do Something with r
})
.catch((e) => {
    console.log("Error while fetching value: ", e);
});

Hope this helps :)

Mohammed Amir Ansari
  • 2,311
  • 2
  • 12
  • 26