2015-09-25 81 views
4

我正在使用新的office.js。我正在使用返回承诺的Excel.run功能。我对图书馆实施的承诺模式有疑问。使用Excel.run链接Office.js中的承诺

样品都表现出这种模式

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 
}); 

的问题是ctx.sync()。然后,()内所含Excel.run() 它呈现的方式,你不能承诺链按照承诺规范,因为如果你尝试并处理excel.run()以外的then(),你就失去了上下文对象。因此,这个模式似乎在促进嵌套函数调用,这就是承诺应该消除的内容。

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) { 

}); 

这是可能的:

我想做的事情通过链接像这样的顺序多次打电话在一起吗?

回答

1

虽然这是可能的,因为Excel.RequestContext.sync发生在直通价值,Excel.run的目标是管理,它在被传递函数trackedObjects。在Excel.Run后链的承诺,你就必须自己管理trackedObjects,因此击败了Excel.Run的目的。

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

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) 
}); 

正如你所看到的,在上面的代码中,你创造了Excel.run里面的工作表对象,但外面使用它。

如果你有类似Range对象的东西,它会变得有点棘手。范围,不像工作表,而不是拥有持久性ID(它们怎么可能?基本上所有可能的单元组合都有无数个排列)。相反,在Excel.run期间,我们自动创建持久指针,指向由Excel调整并保持跟踪的支持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) 
}) 

它会遇到“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); 
}) 

长话短说:它肯定是可行的,并且可以Excel.run后使用对象。您只需要为需要“跟踪”的任何对象负责内存管理。在上面的例子中,没有理由都要经过这方面的努力,因为你也可以同样有内相同的代码Excel.run(记住,你可以链的承诺的Excel.run内批也不需要在外面做这件事)。但是如果你有一个场景,例如你有一个需要频繁运行的计时器作业(例如,更新股票代码),或者你想创建一个带有特定对象的onclick处理器的按钮,等等上面的技巧可以让你在Excel.run里创建对象,然后在它之外使用它们。

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

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); 
}); 
+3

这应该直接复制到文档中。卓越的见解。谢谢! – user3653075

+0

所以你提到了这个:“你想创建一个带有特定对象的onclick处理程序的按钮等等,上面的技术可以让你在Excel.run中创建对象,然后在它之外使用它们。” 我做的这事,但我发现,如果我叫'。选择()'我对象的身体,我的对象是*不*滚动或突出,但我没有收到任何异常。 我有一个带有表格的Word文档。我添加对特定单元格的引用,将其添加为跟踪对象,并附加一个事件处理程序。但点击没有任何反应。 这有效吗? –

+0

对于有这个问题的人,我误解了上下文同步的本质。在我的初始上下文之外,我不得不打开一个新的'Word.run'来获得一个新的上下文,然后在执行我的'select()'后,在我实际的'trackedObject'上调用'context.sync()'。我认为'setTimeOut'示例很好地说明了这一点,我错过了它。 –