bluebirdjsonix

Why does Promisification fail for some methods but not all?


The jsonix library does not follow the first argument must be an error convention so I decided to use bluebird and promisify it like so:

    return new Promise(function(resolve, reject) {
      try {
        unmarshaller.unmarshalString(xmlResponse,
          function (unmarshalled) {
            ...
            resolve(unmarshalled);
          });
      }
      catch (error) {
        reject(error);
      }
    });

But this hangs indefinitely! Whereas if I simply save the xmlResponse to a file and then process it with a different method: unmarshalFile ... the promisification seems to work just fine!

    return new Promise(function(resolve, reject) {
      try {
        unmarshaller.unmarshalFile('test1.xml',
          function (unmarshalled) {
            ...
            resolve(unmarshalled);
          });
      }
      catch (error) {
        reject(error);
      }
    });

So my question is why would promisification fail for one method but not another?


Solution

  • When I look at the code for jsonix, I don't see any callback function for .unmarshalString() and looking at the implementation, there's nothing async in the implementation and nothing that calls a callback. It just returns the answer directly. So, the function is synchronous, not async and returns its value directly as a return value.

    For reference, .unmarshalURL() and .unmarshalFile() do accept the callback and do have an async implementation - .unmarshalString() is just different.

    So, you don't need to use promises with unmarshaller.unmarshalString(xmlResponse) at all. You could just return the straight value:

    return unmarshaller.unmarshalString(xmlResponse);
    

    If you want to wrap it in a promise for consistency of interface among all three methods, you can do this:

    try {
        return Promise.resolve(unmarshaller.unmarshalString(xmlResponse));
    } catch(err) {
        return Promise.reject(err);
    }
    

    Or, you can use Bluebird's Promise.method() to wrap it for you:

    return Promise.method(unmarshaller.unmarshalString.bind(unmarshaller, xmlResponse));