3

Currently I've started developing some Apps for Office 2013. To develop these apps I'm using office.js which is designed to work with Excel worksheets for example.

Most of the APIs are like:

document.getSelectedDataAsync(p1, p2, function(asyncResult)
{
    if (asyncResult.status == 'success')
        // do something with asyncResult.value
    else if (asyncResult.status == 'fail')
        // show asyncResult.error as Error
});

I don't like this type of asynchronous programming. Rather I prefer to use promises and write something like:

document.getSelectedDataAsync(p1, p2)
    .done(function(result)
    {
        // do something with result
    })
    .fail(function(error)
    {
        // show error message 
    })

Is there any way to use office.js API using promises like above?

mehrandvd
  • 8,806
  • 12
  • 64
  • 111

2 Answers2

1

Sure thing - this example is using the bluebird promise library. Basically, we're converting a callback API to promises:

function promisify(fn){ // take a function and return a promise version
     return function(){
          var args = [].slice.call(arguments);
          return new Promise(function(resolve, reject){
               args.push(function(asyncResult){
                    if(asyncResult.status === 'success') resolve(asyncResult.value);
                    else reject(asyncResult.error);
               }); 
               fn.apply(this, args); // call function   
          }.bind(this)); // fixate `this`
     };
}

This would let you do something like:

document.getSelectedDataPromise = promisify(document.getSelectedDataAsync);
document.getSelectedDataPromise(p1, p2).then(function(result){
   // do something with result
}).catch(function(err){
   // handle error
});
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
0

The simplest form of working around this is by replacing the callback with a custom one which resolves a promise. Note that the below implementation uses the ES6 promises which are available in Chrome:

        function toPromise () {
            var args = Array.prototype.slice.call(arguments);
            var self = this;
            return new Promise(function (reject, resolve) {
                var callback = function () {
                    if (arguments[0] instanceof Error) {
                        return reject.apply(null, arguments);
                    }

                    resolve.apply(arguments);
                };

                args.push(callback);
                self.apply(self, args);
            });
        }

        Function.prototype.toPromise = toPromise;

        document.getSelectedDataAsync.toPromise(p1, p2).then(function () {
            //success
        }).catch(function () {
            //error
        });
Georgi-it
  • 3,676
  • 1
  • 20
  • 23
  • Thanks, but I'm not using ES 6. And I'm looking for an easier way, maybe a library which made this happen. Like new versions of jQuery which supports promise pattern for their ajax calls. – mehrandvd Apr 20 '15 at 10:01
  • You can replace the promises with whatever you like. And if no such library exists then you should consider doing it yourself. – Georgi-it Apr 20 '15 at 10:02
  • Resolution is always of a single thing. – Benjamin Gruenbaum Apr 20 '15 at 10:07