编程语言
首页 > 编程语言> > 在JavaScript API for Office中使用promises(ctx.sync)编写循环的最佳方法

在JavaScript API for Office中使用promises(ctx.sync)编写循环的最佳方法

作者:互联网

有许多线程讨论如何保证循环中promises的执行顺序.我想知道Office API加载项JavaScript API的最佳实践.大多数情况下,有问题的承诺是ctx.sync().

这是一个逐个打印Excel范围列表地址的代码段.测试表明它很好地尊重Excel范围的顺序.但问题是是否以及如何保证执行顺序?

function loadAll () {
   var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"];
   var sheet = "Sheet1";
   for (var i = 0; i < ranges.length; i++) {
       loadRange(ranges[i], sheet);        
   }
}

function loadRange (range, sheet) {
   Excel.run(function (ctx) { 
       var r = ctx.workbook.worksheets.getItem(sheet).getRange(range);
       r.load('address');
       return ctx.sync().then(function() {
          console.log(r.address);
       });
   });
}

有人可以帮忙吗?

解决方法:

因为Excel.run返回一个Promise,你可以用.then和保证顺序链接它.即,

Excel.run(function(ctx) { ... return ctx.sync(); ... })
    .then(function() {
        return Excel.run(function(ctx) { ... return ctx.sync(); ... })
    })
    .then(function() {
        return Excel.run(function(ctx) { ... return ctx.sync(); ... })
    });

话虽如此……这将是非常低效的.一个更好的方法是在一个批处理中加载所需的所有对象,只创建一个网络往返(对于Excel Online尤为重要……但即使在桌面上也很明显):

function loadAll () {
    Excel.run(function(ctx) {
        var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"];
        var sheet = "Sheet1";

        var loadedRanges = [];
        for (var i = 0; i < ranges.length; i++) {
            var r = ctx.workbook.worksheets.getItem(sheet).getRange(ranges[i]);
            r.load('address');
            loadedRange.push(r);
        }

        return ctx.sync()
            .then(function() {
                for (var i = 0; i < loadedRanges.length; i++) {
                    console.log(loadedRanges[i].address);
                }
            });
    });
}

UPDATE

根据评论,如果您最终需要执行彼此依赖的单独任务,并且每个任务都需要往返,因此需要通过链接Excel.run进行排序,我建议如下:

function loadAll () {
    var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"];
    var sheet = "Sheet1";

    // Create a starter promise object
    var promise = new OfficeExtension.Promise(function(resolve, reject) { resolve (null); });

    for (var i = 0; i < ranges.length; i++) {
        // Create a closure over i, since it's used inside a function that won't be immediately executed.
        (function(i) {
            // Chain the promise by appending to it:
            promise = promise.then(function() {
                return loadRange(ranges[i], sheet);
            })
        })(i);       
    }
}

function loadRange (range, sheet) {
    return Excel.run(function (ctx) { 
        var r = ctx.workbook.worksheets.getItem(sheet).getRange(range);
        r.load('address');
        return ctx.sync().then(function() {
            console.log(r.address);
        });
    });
}

~Michael Zlatkovsky,Office Extensibility团队的开发人员,MSFT

标签:javascript,asynchronous,promise,office-js,ms-office
来源: https://codeday.me/bug/20190929/1832110.html