2016-06-21 20 views
0

(*私の最初の質問を修正しました。*)約束から値を返す:コールバックまたは約束?

私はExcelワークブックを再計算し、所要時間をプリントする非同期関数calculateを持っています。

次に、私はそれを記録できるように、計算時間を返す関数を作りたいと思います。非同期関数が値を返すようにします。私は仕事、次の2つの方法を、複数のスレッドを読んで、書き込み:calculate2promiseを使用している間、私はcalculate1callbackを使用して推測

function test() { 
    var a = []; 
    var pm = new OfficeExtension.Promise(function(resolve, reject) { resolve (null); }); 

    pm 
     .then(function() { return calculate1('FullRebuild', function (t) { 
      a.push(t); }); }) 
     .then(function() { return calculate1('FullRebuild', function (t) { 
      a.push(t); }); }) 
     .then(function() { return calculate2('FullRebuild').then(function (result) { 
      a.push(result); }); }) 
     .then(function() { return calculate2('FullRebuild').then(function (result) { 
      a.push(result); }); }) 
     .then(function() { 
      document.getElementById("b").value += a.toString() + '\n'; }); 
} 

:ここ

function calculate1 (mode, fn) { 
    return Excel.run(function (ctx) { 
     ctx.workbook.application.calculate(mode); 
     var before = performance.now(); 
     return ctx.sync().then(function() { 
      var after = performance.now(); 
      var t = after - before; 
      document.getElementById("b").value += 'inside: ' + t + '\n'; 
      fn(t); 
     }) 
    }) 
} 

function calculate2 (mode) { 
    return new Promise(function (resolve, reject) { 
     return Excel.run(function (ctx) { 
      ctx.workbook.application.calculate(mode); 
      var before = performance.now(); 
      return ctx.sync().then(function() { 
       var after = performance.now(); 
       var t = after - before; 
       document.getElementById("b").value += 'inside: ' + t + '\n'; 
       resolve(t); }) 
      }) 
    }) 
} 

はテストです。誰がもっと良い方法を教えてもらえますか?

また、適切な場所にfn(t)(resp。、resolve(t))と書かれていますか、別のthenに貼り付ける必要がありますか?

PS:Excel.runおよびctx.sync()は、JavaScript API for Officeの機能です。彼らは両方とも約束を返す。

+2

を取るブロック -

約束の利便性は、それがコールバックのネストを回避していることですこれを見てくださいhttp://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it。コールバックと約束をミックスしています。あなたが望むものを解決する 't'を計算させることをお勧めします。 – Putty

+0

私の初期のコールバックによる方法は間違っていませんでした(エラーメッセージは何か他のものが原因でした)。私の更新を見てください... – SoftTimur

+0

あなたが好きなものは「より良い」ものです。 – zerkms

答えて

1

calculate1()は約束とコールバックの悪い組み合わせであり、calculate2()Explicit Promise Construction Antipatternです。ここで

はあなたが正しく余分な無駄なく約束を使用する方法である。

function calculate1 (mode) { 
    return Excel.run(function (ctx) { 
     ctx.workbook.application.calculate(mode); 
     var before = performance.now(); 

     return ctx.sync().then(function() { 
      var after = performance.now(); 
      var t = after - before; 
      document.getElementById("b").value += 'inside: ' + t + '\n'; 

      return t; 
     }); 
    }); 
} 

そして、あなたはこのようにそれを消費することができます。代わりにコールバックを渡す - - 戻り値は約束に包まれたと同じように解決する必要がありますが、非同期関数が値を返すようにしたい場合は

return calculate1('FullRebuild') 
    .then(function(res) { 
     a.push(res); 
     return calculate1('FullRebuild'); 
    }) 
    .then(function(res) { 
     a.push(res); 
     return calculate1('FullRebuild'); 
    }) 
    .then(function(res) { 
     a.push(res); 
     return calculate1('FullRebuild'); 
    }) 
    .then(function(res) { 
     a.push(res); 
     document.getElementById("b").value += a.toString() + '\n'; 
    }); 
+0

'Promise'コンストラクタは' Excel.run'をラップするのに実際に必要かもしれません。それでも、反パターンを避けるためには、 'resolve(ctx.sync()then then(...))'のようになります。 – Bergi

+0

コードがうまくいきます... 'resolve(t)'が値を渡すのによく使われます。 'then'の' function(res){...} 'を返します。ところが、あなたは 'return t'を直接使うのですが、なぜそれが可能で、どう呼ばれますか? – SoftTimur

+1

@SoftTimur '約束'関数は、約束していないコードから約束を作成するために必要です。 'Excel.run()'と 'ctx.sync()'は約束しているので、ここで 'resolve()'は必要ありません。これが動作する理由は、 'then()'は 'then()'の中で返される値に解決する約束を返します。約束は 'then()'の中に返され、 'then()'によって返される約束はその約束とその解決または拒絶を「採用する」でしょう。 – JLRishe

0

:それはあなたの試みよりもかなり少ないの機能を使用することに注意してくださいあなたの2番目の例では。コールバックが別のコールバック... を必要とし、方法のエラーが最も近いPromise.catchに伝播しているとき>()

function calculate2 (mode) { 
    return new Promise(function (resolve, reject) { 

     Excel.run(function (ctx) {  
      ctx.workbook.application.calculate(mode); 
      var before = performance.now(); 

      ctx.sync().then(function() { 
       var after = performance.now(); 
       var t = after - before; 

       resolve(t); 
      }) 
     }) 
    }) 
} 

calculate2('FullRebuild') 
    .then(function (t) { 
     document.getElementById("b").value += 'inside: ' + t + '\n'; 
     // the return value of a promise resolver is wrapped in a promise too 
     // and the value of t will be available as parameter of the following .then(funtion(t)) block 
     return t; 
}) 
.catch(function(err) { 
    // Addresses potential async errors raised since calling calculate2() 
});