2016-06-18 7 views
2

ループ内の約束の実行順序を保証することについて議論する多くのスレッドがあります。 OfficeアドインのJavaScript APIのベストプラクティスは何ですか?ほとんどの場合、問題の約束はctx.sync()です。OfficeのJavaScript APIで約束(ctx.sync)を持つループを書くための最良の方法

ここには、Excel範囲のリストのアドレスを1つずつ表示するスニペットがあります。このテストは、Excelの範囲の順番を尊重することを示しています。しかし、質問どうすれば実行順序を保証するかどうかはですか?

function loadAll() { 
    var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"]; 
    var sheet = "Sheet1"; 
    for (var i = 0; i < ranges.length; i++) { 
     loadRange(ranges[i], sheet);   
    } 
} 

function loadRange (range, sheet) { 
    Excel.run(function (ctx) { 
     var r = ctx.workbook.worksheets.getItem(sheet).getRange(range); 
     r.load('address'); 
     return ctx.sync().then(function() { 
      console.log(r.address); 
     }); 
    }); 
} 

助けてもらえますか?

+0

実行順序はなぜ気になるのですか? 'Excel.run'は何を返しますか? – Bergi

+0

Excel.run()は、Excelオブジェクトモデルに対してアクションを実行するバッチスクリプトを実行します。バッチコマンドには、ローカルJavaScriptプロキシオブジェクトとローカルオブジェクトとExcelオブジェクト間の状態を同期させ、解決を約束するsync()メソッドの定義が含まれています。 ([概要](http://dev.office.com/docs/add-ins/excel/excel-add-ins-javascript-programming-overview) – SoftTimur

+0

私は実行命令を気にします...私は行くつもりです'loadRange'や' console.log(r.address) 'のような複雑なものには、それらは順序に依存しています... – SoftTimur

答えて

3

Excel.runはPromiseを返しますので、.thenとチェーンして注文を保証することができます。例えば、

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

言われていることです...これはかなり非効率的です。より良いアプローチは、あなたが唯一のネットワーク(エクセルオンラインで特に重要...それでも、デスクトップ上の目立つ)の往復を作成し、1回分に必要なすべてのオブジェクトをロードするために、次のようになります。

function loadAll() { 
    Excel.run(function(ctx) { 
     var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"]; 
     var sheet = "Sheet1"; 

     var loadedRanges = []; 
     for (var i = 0; i < ranges.length; i++) { 
      var r = ctx.workbook.worksheets.getItem(sheet).getRange(ranges[i]); 
      r.load('address'); 
      loadedRange.push(r); 
     } 

     return ctx.sync() 
      .then(function() { 
       for (var i = 0; i < loadedRanges.length; i++) { 
        console.log(loadedRanges[i].address); 
       } 
      }); 
    }); 
} 

UPDATE

コメントのとおり、あなたが Excel.runの連鎖を経由して、配列決定する必要がないので、お互いに依存し、それぞれが往復を必要とすること、および個別のタスクを実行する必要が終わるん場合は、次のよう は

、私は何かをお勧めします:

function loadAll() { 
    var ranges = ["A:A", "B:B", "C:C", "D:D", "E:E"]; 
    var sheet = "Sheet1"; 

    // Create a starter promise object 
    var promise = new OfficeExtension.Promise(function(resolve, reject) { resolve (null); }); 

    for (var i = 0; i < ranges.length; i++) { 
     // Create a closure over i, since it's used inside a function that won't be immediately executed. 
     (function(i) { 
      // Chain the promise by appending to it: 
      promise = promise.then(function() { 
       return loadRange(ranges[i], sheet); 
      }) 
     })(i);  
    } 
} 

function loadRange (range, sheet) { 
    return Excel.run(function (ctx) { 
     var r = ctx.workbook.worksheets.getItem(sheet).getRange(range); 
     r.load('address'); 
     return ctx.sync().then(function() { 
      console.log(r.address); 
     }); 
    }); 
} 

〜Office拡張性チームの開発者であるMichael Zlatkovsky

+0

アドレスをロードするのは良い例ではありません。実際には、私はセルの値と数式を段階的に操作しています。私は直列の非同期呼び出しを実現するためにループでチェーンする必要があります:現在の ''のセルの値と数式は ''その前の ''の操作に依存します。ネットワーク往復を作成することが期待されます。この場合、再帰や 'Array.prototype.reduce()'などをお勧めしますか? – SoftTimur

+0

私の更新された答えを参照してください –

+0

この素晴らしい構造、マイケルありがとうございます...さらに、 'loadAll'の最後に' return promise'を追加すると、 'loadAll'の後に' then'を追加することができます。 、 'globalPromise.then(f1).then(f2).then(loadAll).then(f4)...'となります。 – SoftTimur

関連する問題