2017-02-11 9 views
1

У меня есть ситуация в моем JavaScript, где я создаю ряд обещаний, которые я хочу приложить then/catch условиях каждому, чтобы иметь дело с отдельными проблемами.JSHint, for Loops, Promises и одна надоедливая ошибка lint

Я использую библиотеку Promise RSVP, которая позволяет мне использовать allSettled, чтобы определить, когда все обещания были разрешены. RSVP's allSettled действительно дает мне оценку результата того, что удалось, и что не удалось в конце всех обещанных обещаний, но добавив/catch к каждому обещанию. Я могу лучше контролировать, что делать, если конкретное обещание не выполнено (например, приглашать пользователя на повторную попытку, используя только те, которые не выполнялись, и т. д.).

Используя мой верный линт (JSHint), я получаю «Don't make functions within a loop.» кричать на меня, и я действительно хочу, чтобы иметь возможность прикрепить условия then/catch к каждому Promise без такого рода ошибки пуха появляющегося.

Мне любопытно, как другие люди обошли ошибку 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:

Я был действительно интересно, разница в производительности с for, forEach и map так, используя ответы предоставленные @rasmeister и @hacker rdave я разработал тест JSPerf, чтобы попытаться увидеть, какие из петли были более производительным (я бросил в тесте while для удовольствия): 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>

Это собрать обещания в массив, где вы можете ответить на все м.

0

Вам просто нужно удалить определения функций из цикла - вы можете извлечь всю логику из цикла в одну функцию, а затем использовать это в forEach:

people.forEach(sendMessage); 

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

    sendMessagesToPeople.push(trySendMessageToPerson); 
} 
0

Вы могли бы определить эти две функции, которые передаются then и catch - и что теперь определены в каждой итерации - только один раз:

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

... а потом:

let trySendMessageToPerson = sendMessageToPerson(people[i], "Hi there!") 
    .then(addSuccess) 
    .catch(addFailure)