2017-02-11 6 views
1

私は自分のJavaScriptに、個々の問題に対処するためにそれぞれthen/catchという条件を付けたいといういくつかの約束事を出しています。JSHint、For Loops、Promises、1つの厄介な糸くずりエラー

私はallSettledを使用して、すべての約束がいつ解決されたかを判断できるRSVP Promiseライブラリを使用しています。 RSVPのallSettledは、すべての決済済み約束の終了時に成功したものと失敗したものの出力を評価しますが、then/catchを各約束に追加することで、特定の約束が満たされない場合失敗したものだけを使用して再試行するように促すなど)。

私の信頼できるリンター(JSHint)、私は得続けるの使用「Don't make functions within a loop.」私に戻って叫び、そして私は本当にアップトリミングリントこの種のエラーなく、各約束にthen/catch条件を付けることができるようにしたいです。

私は、JSHintのエラーを回避するためにJSHintのエラーを回避する方法を知りました(JSHintルールを変更するだけでなく、良いルールだと思います) then/catchユースケースです。

ここでは例です:

let Promise = RSVP.Promise 
 
let people = ['Marty McFly', 'Doc', 'Robocop', 'Terminator', 'Bozo'] 
 
let sendMessagesToPeople = [] 
 
let thoseSucceeded = [] 
 
let thoseFailed = [] 
 

 
// Dummy Promise method to send a message to a person 
 
function sendMessageToPerson (person, msg) { 
 
    console.log(`Sending message to ${person}...`) 
 
    return new Promise((resolve, reject) => { 
 
    setTimeout(() => { 
 
     if (Math.random() > 0.5) { 
 
     console.log(`✔︎ Sent "${msg}" to ${person}`) 
 
     resolve(person, msg) 
 
     return 
 
     } 
 
     console.log(`✘ Failed sending "${msg}" to ${person}`) 
 
     reject(person, msg) 
 
    }, 1000 + (Math.random() * 2000)) 
 
    }) 
 
} 
 

 
// Generate the array of Promises for allSettled to process 
 
for (let i = 0; i < people.length; i++) { 
 
    let trySendMessageToPerson = sendMessageToPerson(people[i], "Hi there!") 
 
    /* Illegal, according to JSHint */ 
 
    .then(() => { 
 
     thoseSucceeded.push(people[i]) 
 
    }) 
 
    .catch(() => { 
 
     thoseFailed.push(people[i]) 
 
    }) 
 

 
    sendMessagesToPeople.push(trySendMessageToPerson) 
 
} 
 

 
RSVP.allSettled(sendMessagesToPeople).then(() => { 
 
    console.log(`Succeeded: ${thoseSucceeded.length}, Failed: ${thoseFailed.length}`) 
 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rsvp/3.3.3/rsvp.min.js"></script>

EDIT:

私は答えを使用してforforEachmapとの性能の違いに関しては本当に興味がありました@rasmeisterと@hackerによって与えられるrdave私は(私も楽しみのためwhileテストに投げた)よりパフォーマンスしたループのかを確認しようとするJSPerfテストを考案:私のテストの結果で https://jsperf.com/for-foreach-map-while-loop-performance-testing

は乱暴に変わり、非常に決定的でないので、私は持っていますどのループの実装がパフォーマンスに優れているのかわかりませんが、読みやすさの面ではmapオプションを使用しなければならないと思います。

答えて

0

let Promise = RSVP.Promise 
 
let people = ['Marty McFly', 'Doc', 'Robocop', 'Terminator', 'Bozo'] 
 
let thoseSucceeded = [] 
 
let thoseFailed = [] 
 

 
// Dummy Promise method to send a message to a person 
 
function sendMessageToPerson (person, msg) { 
 
    console.log(`Sending message to ${person}...`) 
 
    return new Promise((resolve, reject) => { 
 
    setTimeout(() => { 
 
     if (Math.random() > 0.5) { 
 
     console.log(`✔︎ Sent "${msg}" to ${person}`) 
 
     resolve(person, msg) 
 
     return 
 
     } 
 
     console.log(`✘ Failed sending "${msg}" to ${person}`) 
 
     reject(person, msg) 
 
    }, 1000 + (Math.random() * 2000)) 
 
    }) 
 
} 
 

 
let sendMessagesToPeople = people.map((person) => { 
 
    return sendMessageToPerson(person, "Hi there!") 
 
    .then(() => { 
 
     thoseSucceeded.push(person) 
 
    }) 
 
    .catch(() => { 
 
     thoseFailed.push(person) 
 
    }) 
 
}) 
 

 
RSVP.allSettled(sendMessagesToPeople).then(() => { 
 
    console.log(`Succeeded: ${thoseSucceeded.length}, Failed: ${thoseFailed.length}`) 
 
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rsvp/3.3.3/rsvp.min.js"></script>

これは、あなたが、その後メートル、すべてに対応できる配列に約束を集めるでしょう。

people.forEach(sendMessage); 

function sendMessage(person) { 
    let trySendMessageToPerson = sendMessageToPerson(person, "Hi there!") 
    .then(thoseSucceded.push) 
    .catch(thoseFailed.push); 

    sendMessagesToPeople.push(trySendMessageToPerson); 
} 
0

その後、

let addSuccess = person => thoseSucceeded.push(person); 
let addFailure = person => thoseFailed.push(person); 

...と::

一度だけ - thencatchに渡される - それは、現在、各反復で定義されています
let trySendMessageToPerson = sendMessageToPerson(people[i], "Hi there!") 
    .then(addSuccess) 
    .catch(addFailure) 
0

あなたはするものの二つの機能を定義することができます:あなたはforEachであることを使用し、その後、一つの関数にループからすべてのロジックを抽出することができます - あなただけのループから関数定義を削除する必要が