2015-09-25 64 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'示例很好地說明了這一點,我錯過了它。 –