0

I am trying to find some way to write my general promisify function to use async and wait with socket.io
Here is my code the first one fail to finish while the second success without problem.

What is the difference between these two? and why would the first one fail?

function promisify (func) {
    return new Promise((resolve, reject) => func(() => {
        resolve()    
        console.log('closeServer')
    }))}
async function timer1 () {
    await Promise.resolve(promisify(server.close))
}



function closeServer () {
    return new Promise((resolve, reject) => server.close(() => {
        resolve()
        console.log('closeServer')
    }))}
async function timer2 () {
    await Promise.resolve(closeServer())
}

let me show you guys the log,
the second one

> nodemon src/index.js --exec babel-node --presets es2015

[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/index.js --presets es2015`
Server listening at port 3000
^C(node:28061) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: Cannot read property '_handle' of undefined
(node:28061) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

the second

> nodemon src/index.js --exec babel-node --presets es2015

[nodemon] 1.11.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node src/index.js --presets es2015`
Server listening at port 3000
^CcloseServer
patpat
  • 664
  • 1
  • 5
  • 14
  • `why would the first one fail` in what way does it fail? By the way, neither of those functions will ever reject – Jaromanda X Aug 19 '17 at 14:03
  • "*`resolve(); if (false) reject(err)`*" - Wat? – Bergi Aug 19 '17 at 15:43
  • I think this is a duplicate of [How to access the correct `this` / context inside a callback?](https://stackoverflow.com/q/20279484/1048572) - that's the obvious difference between your codes: `close` is not called as a method of `server` when using `promisify`. – Bergi Aug 19 '17 at 15:44

1 Answers1

0

Your first one calls the function immediately and, when it's called back, resolves with undefined. It doesn't do anything to pass along the data, or handle errors; indeed, if if (false) weren't always, well, false, that code would fail with a ReferenceError when trying to take the value of the err identifier.

If you wanted to write a function that would convert a Node-style callback API into a promise-enabled one, it's fairly simple. You assume the callback is the last thing the function expects in its arguments list, and that it calls the callback with the usual err, data arguments:

const promisify = func => (...args) => new Promise((resolve, reject) => {
    func(...args, (err, data) => {
        if (err) {
            reject(err instanceof Error ? err : new Error(err));
        } else {
            resolve(data);
        }
    });
});

It returns a function that, when called, will call the original file passing along all of its arguments plus a callback at the end, and return a promise. When the callback is called, it assumes it's in the usual err, data format and rejects the promise if err is truthy, resolves it otherwise. It ensures that the rejection is an Error (my preference is always to use Error for throw and reject; your style may vary).

Usage:

const readFileP = promisify(fs.readFile);

Then where you want to use the result:

readFileP("filename", "utf-8")
    .then(data => { /* ... */ })
    .catch(err => { /* ... */ });

However, if you search, there are feature-rich libraries out there that do it for you with much more flexibility, and are tested as well.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875