隨着 Timecard 列表的增多,如何查找和管理這許多的 Timecard 也就成了問題。尤爲對於團隊經理而言,他除了本身填寫的 Timecard,還要審覈團隊成員的 Timecard 任務更重。php
這裏我把實際的需求簡化成爲 2 個主要的視圖(但可以提供的效果和實際需求實際上是很是接近的):web
2個門戶視圖有不少種技術方案來實現。promise
JavaScript (SharePoint CSOM)開發,最煩的是其異步回調的機制。全部向服務器發送的操做,都要在回調函數裏面收結果,而後你才能繼續下一步的業務邏輯。緩存
目前我找到的比較容易減輕這個症狀的方案,是用 Deferred。先將調用服務器的操做用 Deferred 包裝,而後用 $.when 來調用並捕獲其返回結果。這樣,至少形式上看上去,後續的業務邏輯操做是緊跟在前面一步的服務器調用後面的,看上去就舒服多了。服務器
也有不少 JavaScript 的函數庫提供了這個問題的解決方案,但在試用以後,我都放棄了。簡單的問題仍是用簡單的方案吧。app
爲了說明這個實現方法,咱們先看一個空的 Deferred 包裝的 SharePoint 調用:異步
1: return $.Deferred(function (dtd) {
2: var web = context.get_web();
3: sp.context.load(web);
4: var failure_callback = Function.createCallback(onSharePointFailed, dtd);
5: sp.context.executeQueryAsync(
6: function () {
7: var title = web.get_title();
8: dtd.resolve();
9: },
10: Function.createDelegate(this, failure_callback));
11: }).promise();
上面的例子中,context 是在調用前初始化好了的 SharePoint Context 全局變量,而 onSharePointFailed 則是預先定義的出錯回調函數。ide
經過上面這樣的形式,就完成了一個最簡單的 Deferred 封裝。函數
爲了使用上面的封裝,咱們先要將其放入一個函數中去:性能
1: var spGetWeb = function () {
2: var web = context.get_web();
3: context.load(web);
4: var failure_callback = Function.createCallback(sp.Failed, dtd);
5: sp.context.executeQueryAsync(
6: function () {
7: var title = web.get_title();
8: dtd.resolve();
9: },
10: Function.createDelegate(this, failure_callback));
11: }).promise();
12: }
好了,下面就能夠開始調用了(這只是個例子,真的要調用,仍是要作不少準備的,好比初始化 context 等等):
1: $.when(spGetWeb())
2: .done(function(){
3: message.succeed("Web is ready.");
4: $.when(spGetList("Time Window"))
5: .done(function(){...})
6: .fail(function(){...});
7: })
8: .fail(function(){
9: message.error("Can't get the web.");
10: }}
上面的例子中,先調用了 spGetWeb,在成功之後(done),接着又調用了 spGetList。這樣,原先像麪條同樣散落的回調業務邏輯,能夠用比較人性化的方式呈現了,咱們也好少死幾個腦細胞。
下面的視頻是實現的效果: