al6x / synchronize

Write asynchronous code as if it's synchronous
http://alexeypetrushin.github.com/synchronize
316 stars 57 forks source link

Please add promise example #56

Open zmorris opened 7 years ago

zmorris commented 7 years ago

Hi, I'm trying to get Synchronize.js working with Inquirer but I've tried everything and can't get it to work with its promises:

package.json

{
  "dependencies": {
    "inquirer": "^3.0.6",
    "synchronize": "^2.0.0"
  }
}

index.js

const inquirer = require('inquirer');
const sync = require('synchronize');

const fiber = sync.fiber;
const await = sync.await;
const defer = sync.defer;

// // works
// inquirer.prompt([{
//     type: 'input',
//     name: 'first_name',
//     message: 'What\'s your first name'
// }]).then(function (answers) {
//   console.log('First name:', answers.first_name);
// });

// doesn't work
fiber(function() {
  const answers = await( 
    inquirer.prompt([{
      type: 'input',
      name: 'first_name',
      message: 'What\'s your first name'
    }]).then(defer())
  );

  console.log(answers);
});
$ yarn
$ node index.js
? What's your first name? Zack

/Users/zackmorris/Desktop/testing/appium-vynyl/node_modules/synchronize/sync.js:111
        fiber.throwInto(err)
              ^
[object Object]

I've tried every permutation, even variations of https://github.com/alexeypetrushin/synchronize/issues/41 but can't get it to work.

Can you update your documentation for promises? Or else show how to de-promisify something? I tried wrapping the promise in my own callback function to fit the form of your examples but it still didn't work for some reason.


By comparison, here's the same example with asyncawait and Inquirer:

package.json

{
  "dependencies": {
    "asyncawait": "^1.0.6",
    "inquirer": "^3.0.6"
  }
}

index.js

const async = require('asyncawait/async');
const await = require('asyncawait/await');
const inquirer = require('inquirer');

async (function () {
  const answers = await(
    inquirer.prompt([{
      type: 'input',
      name: 'first_name',
      message: 'What\'s your first name?'
    }])
  );

  console.log('First name:', answers.first_name);
})();
$ yarn
$ node index.js
? What's your first name? Zack
First name: Zack

Thanx!

zakdav commented 7 years ago

You can use or give a look to my module node-fibers-synchronize-helper that uses this module synchronize

index.js

const inquirer = require('inquirer'); var synchProm = require('node-fibers-synchronize-helper')

synchProm.executeSynch(function () {

 var answers = synchProm.executePromiseFiberFn(inquirer, inquirer.prompt, [{
     type: 'input',
     name: 'first_name',
     message: 'What\'s your first name'
}])

 console.log(answers);

}, function (err, res) { if (err) console.log("err", err) else console.log("OK:", res) })

result: davide@davide-kubuntu:~/node/test/synchronizeTests$ node . ? What's your first name davide { first_name: 'davide' }

You can give a look at my implementation

https://github.com/zakdav/node-fibers-synchronize-helper/blob/master/index.js

In your case i called this methods

var executePromiseFiberIntFn = function (obj, fn, params) { var defer = sync.defer(); runPromiseFiberFn(obj, fn, params, defer) var res = sync.await(); return res; }

var runPromiseFiberFn = function (obj, fn, params, defer) { fn.apply(obj, params).then(function (res) { //fn().then(function (res) { defer(null, res) }).catch(function (e) {

    defer(e)
})

}

dsandber commented 6 years ago

So there isn't any "straight" (without additional code/helpers) way of calling inquirer using synchronize? I tried various permutations of await, defer(), etc, and also could never get it working.

dreusel commented 3 years ago

The problem is that then() will pass the result as the first argument, while defer(), generates a classical node-style callback which, like any classical node callback, expects any error as the first argument and the result as the second argument. This is a plain 'how to combine promises with callbacks' type of thing. Instead, try:

fiber(function() {
  // Create the defer first, otherwise await is called before the defer is created.
  const d = defer();
  const answers = await( 
    inquirer.prompt([{
      type: 'input',
      name: 'first_name',
      message: 'What\'s your first name'
    }]).then(r => d(null, r))
  );

  console.log(answers);
});

You could make things look slightly nicer by using nodes util.callbackify, but hopefully my example indicates more clearly what's actually happening.