用Excel.run()链接Office.js中的承诺 [英] Chaining Promises in Office.js with Excel.run()

查看:146
本文介绍了用Excel.run()链接Office.js中的承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的office.js。我正在使用返回承诺的Excel.run功能。我有一个关于图书馆承诺模式的问题。



样本都显示这种模式

  
//设置东西

返回ctx.sync )。(function(){
//调用另一个函数链接操作
});

})然后(function(){
/ / do do something if(如果你想要
})。catch(function(error){
handle errors
});

问题是Excel.run()中包含的ctx.sync()。then b $ b如果您尝试处理Excel.run()以外的then()
,那么您无法按照承诺规范链接承诺,因为丢失上下文对象。因此,模式似乎是促进嵌套函数调用,这是应该消除的承诺。



我想要做的是通过链接将这些调用序列在一起: p>

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

});

这可能吗?

解决方案

一般来说, Excel.run 的目的是针对OM进行顺序操作,最后自动清理。也就是说, Excel.run 创建一个上下文,运行你的操作,然后清理分配的任何主机对象。



就是说,正如Gab Royer所说,你可以把对象传递出去。而且,每个Excel对象通过.context属性都有一个指向其上下文的指针。所以例如,你可以这样做:

  Excel.run(function(ctx){
var worksheet = ctx.workbook.worksheets.getActiveWorksheet();
返回ctx.sync(工作表);
})然后(function(worksheet){
worksheet.name = test
return worksheet.context.sync();
})。catch(function(e){
console.log(e)
});

您可以看到,在上面的代码中,您已经在<$ c中创建了工作表对象$ c> Excel.run ,但是在外面使用它。



如果你有一个像Range对象的东西,它会有点棘手。范围与工作表不同,do 具有持久ID(它们怎么样?基本上是所有可能的单元格组合的无数排列)。相反,在 Excel.run 期间,我们会自动创建持久性指针,以便通过Excel调整和保持跟踪的后备范围对象。当$ code> Excel.run 内的批处理完成后,我们告诉主机销毁这些引用。所以如果你有这样的代码:

  Excel.run(function(ctx){
var range = ctx.workbook.getSelectedRange();
return ctx.sync(range);
})然后(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);
返回ctx.sync(范围);
})然后(function(range){
range.format.fill.color =red;
return range.context.sync();
} ).then(function(){
//尝试清理任何孤立引用
range.context.trackedObjects.remove(range);
range.context.sync(); //不需要等待它,因为它只是最后的清理调用
})。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);
返回ctx.sync()
。 (){
//针对OM的一些操作集,现在已经加载了values
//属性,可以从范围对象读取
})
.then(ctx.sync)
.then(function(){
//针对OM的另一组动作,大概是在
之后//另一个需要负载的操作(否则可能有
//是相同的一部分。)如上所述)
})
.then(ctx.sync)
.then(function(){
//最后一组动作
});
})。catch(function(error){
console.log(Error:+ error);
});


I’m working with the new office.js. I’m using the Excel.run functionality that returns a promise. I have a question about the promises pattern implemented by the library.

The samples all show this pattern

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

The problem is the ctx.sync().then() contained within Excel.run() The way it is presented, you can’t chain promises in accordance with the promises spec because you lose the context object if you try and handle the then() outside of Excel.run() So, the pattern seems to be promoting nested function calls, which is what promises are supposed to eliminate.

What I want to do is sequence several calls together through chaining like this:

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

});

Is this possible?

解决方案

In general, the purpose of Excel.run is for a sequential operation against the OM with automatic cleanup at the end. That is, Excel.run creates a context, runs you operation, and then cleans up any host objects that were allocated.

That being said, as mentioned by Gab Royer, you can pass objects out. And moreover, each Excel object has a back-pointer to its "context" via the ".context" property. So for example, you can do this:

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

As you can see, in the code above, you had created the worksheet object inside the Excel.run, but are using it outside.

If you have something like a Range object, it gets a little trickier. Ranges, unlike Worksheets, do not have persistent IDs (How could they? There is essentially a countless number of permutations of all possible combinations of cells). Instead, during Excel.run, we automatically create persistent pointers to the backing Range objects that get adjusted and kept-track-of by Excel. When the batch inside of Excel.run completes, we tell the host to destroy these references. So if you had code like this:

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

It would run into an "InvalidObjectPath" error.

However, you can opt out of the tracked-object cleanup by manually adding the object to the ctx.trackedObjects collection. In doing this, however, you are taking it upon yourself to clean up at the end -- and you need to be extra careful, to remember to cleanup on not only on success, but on failure. Otherwise, you're essentially creating a memory leak that will keep slowing down the Excel host application.

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

Long story short: it is certainly doable, and you can use objects after Excel.run. You'll just need to be responsible for memory-management for any objects that require "tracking". In the example above, there is no reason to go through this effort, since you could just as well have had the same code inside of Excel.run (remember, you can chain promises within the batch inside of Excel.run, too -- no need to do this on the outside). But if you have a scenario, where, say, you have a timer job that needs to run every so often (e.g., to update a stock ticker), or you want to create a button with an onclick handler for a particular object, etc. the technique above will let you create the objects inside of Excel.run, and then use them outside of it.

PS: With regards to the pattern requiring nesting: It is true that if you need to chain ctx.sync() calls within Excel.run, you will end up with a layer of nesting -- but just a single extra layer. Within, you still would still be able to chain your promises without the callback pyramid. E.g.,:

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

这篇关于用Excel.run()链接Office.js中的承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆