2017-09-11 1 views
1

['https://1.2.3.4'、 'https://httpbin.org/delay/3'、 'https://httpbin.org/status/500']のURLからベストURL(ローカルキャッシュ)を探していて、5秒のタイムアウトで最適なものを選択してください。それ以外の場合は「https://httpbin.org/status/200」にフォールバックします。この人工的な例では、 'https://httpbin.org/delay/3'が勝つはずです!フェッチするにはどのように最適なURLを選択しますか?

function fallback(response) { 
 
    if (response.ok) { 
 
    return response; 
 
    } 
 
    console.log("Trying fallback") 
 
    return fetch("https://httpstat.us/200") // absolute fallback 
 
} 
 

 
var p = Promise.race([ 
 
    fetch('https://1.2.3.4'), // will fail 
 
    fetch('https://httpbin.org/delay/3'), // should be the winner 
 
    fetch('https://httpbin.org/status/500'), // will fail 
 
    new Promise(function(resolve, reject) { // Competing with a timeout 
 
     setTimeout(() => reject(new Error('request timeout')), 5000) 
 
    }) 
 
    ]) 
 
    .then(fallback, fallback) 
 
    .then(console.log)

私が持っているコードは、任意の戻りPromise raceは終了となる問題があります。 「https://httpbin.org/delay/3」が正しくレースに勝つように、これを最もうまく構築するにはどうすればよいですか?

+0

を経由して来る、あなたは約束を拒否する意味ですか? –

+0

サーバーが到達不能でない限り、約束は常に成功するはずです。何が起きるかは、サーバーが応答しますが、ステータスは200ではないため、有効なエンドポイントではありません。 – Eladian

答えて

-1

function race(promises) { 
 
    return Promise.race(Object.keys(promises).map((key) => { 
 
     return promises[key] 
 
    })) 
 
    .then(function(response) { 
 
     console.log(response); 
 
     if (!response.ok) { 
 
     delete promises[response.url]; 
 
     return race(promises) 
 
     } else if (Object.keys(promises).length == 0 || response.url == 'timeout') { 
 
     console.log('returning default'); 
 
     return fetch("https://httpstat.us/200") 
 
     } 
 

 
     return response; 
 
    }) 
 
} 
 

 
race({ 
 
    'https://1.2.3.4': fetch('https://1.2.3.4'), 
 
    'https://1.2.3.4': fetch('https://1.2.3.4'), 
 
    'timeout': new Promise(function(resolve, reject) { 
 
    setTimeout(() => reject(new Error('request timeout')), 5000) 
 
    }) 
 
}).then(function(response) { 
 
    console.log(response) 
 
}).catch(function(err) { 
 
    console.log('err:'); 
 
    console.log(err.message) 
 
    return fetch("https://httpstat.us/200") 
 
}).then(function(defaultFetch) { 
 
    console.log('timed out requesting failed urls, getting default:'); 
 
    console.log(defaultFetch); 
 
});

+0

ではなく、!response.okを500のような特定のエラーよりもテストしています。また、スニペットを挿入して実行することもできますか? :) – hendry

+0

挿入されたスニペット – Eladian

+0

これは近いですが、すべてが失敗した場合、フォールバックは試されません –

0

Promise.race([ 
 
    new Promise(resolve => { 
 
    const ignoreError =() => {} 
 
    // first to resolve with .ok gets to resolve the promise 
 
    const resolveIfOk = res => res.ok && resolve(res) 
 
    fetch('https://httpbin.org/delay/20').then(resolveIfOk, ignoreError) 
 
    fetch('https://httpbin.org/delay/3').then(resolveIfOk, ignoreError) 
 
    fetch('https://1.2.3.4').then(resolveIfOk, ignoreError) 
 
    return; 
 
    }), 
 
    new Promise((_, reject) => setTimeout(() => reject(new Error('timed out')), 4000)) // reject if timeout 
 
]).then(function(value) { 
 
    console.log("Success", value); 
 
    return value 
 
}, function(reason) { 
 
    console.log("Going to use fallback", reason); 
 
    return fetch('https://httpstat.us/200') 
 
}).then(console.log)

ソリューションは、あなたが "失敗" と言うときhttps://twitter.com/secoif

関連する問題