2016-10-09 5 views
5

私はAとBという2つの約束を持っていますが、そのうちの1つだけが成功するでしょう。私はPromise.raceに似た何かを探していますが、それは実現する最初の約束しか返しません。私はES6からの約束を使用しています。最初に約束を達成

+0

あなたは 'Promise.any'([ブルーバード](http://bluebirdjs.com/docs/api/promise.any.html)を探している、[クリード](https://github.com/briancavalier/creed#any-iterable-promise-ea-promise-ea)、[WinJS](https://msdn.microsoft.com/en-us/library/windows/apps/br229660.aspx)、... ) – Bergi

答えて

10

それが反転した後、最初の成就の約束に対応する第1の拒否約束、上拒否しているため、約束の極性を反転し、次にあなたがPromise.allを使用することができます。

const invert = p => new Promise((res, rej) => p.then(rej, res)); 
 
const firstOf = ps => invert(Promise.all(ps.map(invert))); 
 

 
// Utility routines used only in testing. 
 
const wait = ms => new Promise(res => setTimeout(() => res(ms), ms)); 
 
const fail = f => Promise.reject(f); 
 
const log  = p => p.then(v => console.log("pass", v), v => console.log("fail", v)); 
 

 
// Test. 
 
log(firstOf([wait(1000), wait(500) ])); 
 
log(firstOf([wait(1000), fail("f1")])); 
 
log(firstOf([fail("f1"), fail("f2")]));

これは、最初に実行された約束の値を返します。すべてが拒否された場合は、拒否理由の配列を返します。

+1

Clever。これは、反転の概念が約束の土地で有用であることを示す初めてのことではありません。 – jfriend00

+0

@ jfriend00このテクニックは、私が追跡できない、元のものではない少なくとも1つの他の答えで示されていました。 –

+0

これは巧妙なハックです。 – Redu

3

あなたが成功し解決する最初の約束をしたいとあなたがその前に来るすべての拒否を無視したい場合は、このようなものを使用することができます

// returns the result from the first promise that resolves 
// or rejects if all the promises reject - then return array of rejected errors 
function firstPromiseResolve(array) { 
    return new Promise(function(resolve, reject) { 
     if (!array || !array.length) { 
      return reject(new Error("array passed to firstPromiseResolve() cannot be empty")); 
     } 
     var errors = new Array(array.length); 
     var errorCntr = 0; 
     array.forEach(function (p, index) { 
      // when a promise resolves 
      Promise.resolve(p).then(function(val) { 
       // only first one to call resolve will actually do anything 
       resolve(val); 
      }, function(err) { 
       errors[index] = err; 
       ++errorCntr; 
       // if all promises have rejected, then reject 
       if (errorCntr === array.length) { 
        reject(errors); 
       } 
      }); 
     }); 
    }); 
} 

を私はあなたがどのように使用できるかが表示されないPromise.race()なぜなら、それは単に最初の約束を報告するだけであり、最初の約束が拒否されれば拒絶を報告するからです。それで、それはあなたがあなたの質問で尋ねたことをやっていません。それは解決する最初の約束を報告することです(たとえそれ以前に拒絶が終わったとしても)。

FYI the Bluebird promise libraryには、このケースを処理できるPromise.some()Promise.any()の両方があります。

+0

'p.then(...)の代わりに' p.then(...、...) 'を使うべきです。 – Bergi

+0

@Bergi - 未処理の拒否はどこにありますか? – jfriend00

+1

'p'が拒否した場合、' p.then(...) 'の結果は拒否され、決して処理されないという約束です。 – Bergi

0
//example 1 
    var promise_A = new Promise(function(resolve, reject) { 
     // выполнить что-то, возможно, асинхронно… 
     setTimeout(function(){ 

      return resolve(10); 
      //return reject(new Error('ошибка')) 
     },10000) 
    }); 

    var promise_B = new Promise(function(resolve, reject) { 
     // выполнить что-то, возможно, асинхронно… 

     setTimeout(function(){ 
      return resolve(100); 
     },2000) 
    }); 


/* 
//[100,10] 
Promise.all([ 
    promise_A,promise_B 
]).then(function(results){ 
    console.log(results) 
}); 
*/ 

//100 
Promise.race([ 
    promise_A,promise_B 
]).then(function(results){ 
    console.log(results) 
}); 
+0

達成する約束。 – mbacvanski