使用Excel.run()在Office.js中链接Promise

use*_*075 4 excel ms-office office365 office-js

我正在使用新的office.js.我正在使用返回promise的Excel.run功能.我对库实现的promises模式有疑问.

样本都显示了这种模式

Excel.run( function (ctx) {

  //set up something

  return ctx.sync().then (function () {
    //call another function somewhere to chain operations
  });

}).then ( function () {
  //do something else if you want
}).catch (function (error) {
  handle errors
});
Run Code Online (Sandbox Code Playgroud)

问题是Excel.run()中包含的ctx.sync().then()它呈现的方式,你不能按照promises规范链接promises,因为如果你试图处理它就丢失了上下文对象然后()在Excel.run()之外()因此,模式似乎是在促进嵌套函数调用,这是承诺应该消除的.

我想要做的是通过链接将几个调用一起排序:

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

});
Run Code Online (Sandbox Code Playgroud)

这可能吗?

Mic*_*oft 9

通常,目的Excel.run是在最后通过自动清理对OM进行顺序操作.也就是说,Excel.run创建一个上下文,运行您的操作,然后清除已分配的任何主机对象.

话虽如此,正如Gab Royer所说,你可以传递出物体.而且,每个Excel对象都有一个通过".context"属性指向其"上下文"的后向指针.例如,你可以这样做:

Excel.run(function (ctx) {
    var worksheet = ctx.workbook.worksheets.getActiveWorksheet();
    return ctx.sync(worksheet);
}).then(function(worksheet) {
    worksheet.name = "Test"
    return worksheet.context.sync();
}).catch(function(e) {
    console.log(e)  
});
Run Code Online (Sandbox Code Playgroud)

如您所见,在上面的代码中,您已在其中创建了工作表对象Excel.run,但在外部使用它.

如果你有类似Range对象的东西,它会变得有点棘手.与工作表不同,范围没有持久性ID(它们怎么可能?所有可能的单元组合基本上存在无数个排列).相反,在此期间Excel.run,我们会自动创建指向由Google调整并保持跟踪的支持Range对象的持久性指针.当批处理内部Excel.run完成时,我们告诉主机销毁这些引用.所以如果你有这样的代码:

Excel.run(function (ctx) {
    var range = ctx.workbook.getSelectedRange();
    return ctx.sync(range);
}).then(function(range) {
    range.format.fill.color = "red";
    return ctx.sync();
}).catch(function(e) {
    console.log(e)  
})
Run Code Online (Sandbox Code Playgroud)

它会遇到"InvalidObjectPath"错误.

但是,您可以通过手动将对象添加到ctx.trackedObjects集合中来选择退出跟踪对象清理.然而,在这样做的过程中,你最终需要自己清理 - 而且你需要格外小心,不仅要记得清理成功,还要记得失败.否则,您实际上是在创建内存泄漏,这将继续减慢Excel主机应用程序的速度.

var range;
Excel.run(function (ctx) {
    range = ctx.workbook.getSelectedRange();
    ctx.trackedObjects.add(range);
    return ctx.sync(range);
}).then(function(range) {
    range.format.fill.color = "red";
    return range.context.sync();
}).then(function() {
    // Attempt to clean up any orphaned references
    range.context.trackedObjects.remove(range);
    range.context.sync(); // don't need to await it, since it's just the final cleanup call
}).catch(function(e) {
    console.log(e);
})
Run Code Online (Sandbox Code Playgroud)

长话短说:它肯定是可行的,你可以使用之后的对象Excel.run.您只需负责任何需要"跟踪"的对象的内存管理.在上面的例子中,没有理由去完成这项工作,因为您可以在Excel.run中使用相同的代码(请记住,您也可以 Excel.run中的批处理中链接promise -不需要在外面这样做).但是,如果您有一个场景,比如说,您有一个需要经常运行的计时器作业(例如,更新股票报价器),或者您想要为特定对象创建一个带有onclick处理程序的按钮,等等上面的技术将允许您在Excel.run中创建对象,然后在它之外使用它们.

PS:至于需要嵌套模式:这是事实,如果你需要链ctx.sync()内Excel.run电话,您将结束与嵌套了一层-而只是一个单一的额外层.在内部,您仍然可以在没有回调金字塔的情况下链接您的承诺.例如,:

Excel.run(function (ctx) {
    var range = ctx.workbook.worksheets.getActiveWorksheet().getRange("A1:C3");
    range.load("values");
    return ctx.sync()
        .then(function () {
            // Some set of actions against the OM, now that the "values"
            // property has been loaded and can be read from the "range" object.
        })
        .then(ctx.sync)
        .then(function () {
            // Another set of actions against the OM, presumably after doing
            // another load-requiring operation (otherwise could have
            // been part of the same .then as above)
        })
        .then(ctx.sync)
        .then(function() {
            // One final set of actions
        });     
}).catch(function(error) {
    console.log("Error: " + error);
});
Run Code Online (Sandbox Code Playgroud)

  • 这应该被复制到文档中.出色的见解.谢谢! (3认同)

Gab*_*yer 1

虽然这是可能的,因为Excel.RequestContext.sync接受传递值,但目标Excel.run是管理传入的函数的 trackedObjects。在Excel.Run您必须自己管理 trackedObjects 之后链接的承诺中,因此违背了 Excel.Run 的目的。

Excel.Run如果您不喜欢添加的缩进,我建议您在外部声明您的函数,或者创建您自己的RequestContext对象。