Работа с office.js с использованием шаблона обещания
В настоящее время я начал разработку некоторых приложений для Office 2013. Для разработки этих приложений я использую office.js, который предназначен, например, для работы с листами Excel.
Большинство API-интерфейсов похожи на:
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
});
Мне не нравится этот тип асинхронного программирования. Скорее я предпочитаю использовать обещания и писать что-то вроде:
document.getSelectedDataAsync(p1, p2)
.done(function(result)
{
// do something with result
})
.fail(function(error)
{
// show error message
})
Есть ли способ использовать API office.js, используя обещания, как указано выше?
2 ответа
Конечно, этот пример использует библиотеку обещаний Bluebird. По сути, мы конвертируем API обратного вызова в обещания:
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`
};
}
Это позволит вам сделать что-то вроде:
document.getSelectedDataPromise = promisify(document.getSelectedDataAsync);
document.getSelectedDataPromise(p1, p2).then(function(result){
// do something with result
}).catch(function(err){
// handle error
});
Самая простая форма обхода этого - замена обратного вызова на пользовательский, который разрешает обещание. Обратите внимание, что в приведенной ниже реализации используются обещания ES6, доступные в 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
});