JSHint、For Loops、Promises 和一个讨厌的 lint 错误
JSHint, For Loops, Promises and one pesky lint error
我的 JavaScript 中有一种情况,我正在生成许多承诺,我想在每个承诺上附加 then
/catch
条件以处理个别问题。
我正在使用 RSVP Promise 库,它让我可以使用 allSettled
来确定何时所有承诺都已解决。 RSVP 的 allSettled
确实让我评估了所有已确定承诺结束时成功和失败的输出,但是通过将 then
/catch
添加到每个 Promise 我可以更好地控制如果未实现特定的 Promise 该怎么办(例如,提示用户仅使用失败的 Promise 重试等)。
使用我可信赖的 linter (JSHint),我不断收到“Don't make functions within a loop.
”的回复,我真的希望能够附加 then
/catch
条件每个 Promise 都不会出现这种 lint 错误。
我很好奇其他人如何绕过 JSHint 错误(除了更改 JSHint 规则。我认为这是一个很好的规则!)或者是否有人对如何处理我生成的 Promises 有更好的想法' 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>
编辑:
我真的很好奇 for
、forEach
和 map
的性能差异,所以使用 @rasmeister 和 @hackerrdave 给出的答案,我设计了一个 JSPerf 测试来尝试查看哪些循环性能更高(为了好玩,我还进行了 while
测试):
https://jsperf.com/for-foreach-map-while-loop-performance-testing
在我的测试中,结果变化很大并且非常不确定,所以我不知道哪个循环实现在性能方面更好,但就可读性而言,我认为我必须选择 map
选项。
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>
这会将承诺收集到一个数组中,然后您可以在其中响应所有承诺。
您只需要从循环中删除函数定义 - 您可以将循环中的所有逻辑提取到一个函数中,然后在 forEach
:
中使用它
people.forEach(sendMessage);
function sendMessage(person) {
let trySendMessageToPerson = sendMessageToPerson(person, "Hi there!")
.then(thoseSucceded.push)
.catch(thoseFailed.push);
sendMessagesToPeople.push(trySendMessageToPerson);
}
您可以定义传递给 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)
我的 JavaScript 中有一种情况,我正在生成许多承诺,我想在每个承诺上附加 then
/catch
条件以处理个别问题。
我正在使用 RSVP Promise 库,它让我可以使用 allSettled
来确定何时所有承诺都已解决。 RSVP 的 allSettled
确实让我评估了所有已确定承诺结束时成功和失败的输出,但是通过将 then
/catch
添加到每个 Promise 我可以更好地控制如果未实现特定的 Promise 该怎么办(例如,提示用户仅使用失败的 Promise 重试等)。
使用我可信赖的 linter (JSHint),我不断收到“Don't make functions within a loop.
”的回复,我真的希望能够附加 then
/catch
条件每个 Promise 都不会出现这种 lint 错误。
我很好奇其他人如何绕过 JSHint 错误(除了更改 JSHint 规则。我认为这是一个很好的规则!)或者是否有人对如何处理我生成的 Promises 有更好的想法' 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>
编辑:
我真的很好奇 for
、forEach
和 map
的性能差异,所以使用 @rasmeister 和 @hackerrdave 给出的答案,我设计了一个 JSPerf 测试来尝试查看哪些循环性能更高(为了好玩,我还进行了 while
测试):
https://jsperf.com/for-foreach-map-while-loop-performance-testing
在我的测试中,结果变化很大并且非常不确定,所以我不知道哪个循环实现在性能方面更好,但就可读性而言,我认为我必须选择 map
选项。
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>
这会将承诺收集到一个数组中,然后您可以在其中响应所有承诺。
您只需要从循环中删除函数定义 - 您可以将循环中的所有逻辑提取到一个函数中,然后在 forEach
:
people.forEach(sendMessage);
function sendMessage(person) {
let trySendMessageToPerson = sendMessageToPerson(person, "Hi there!")
.then(thoseSucceded.push)
.catch(thoseFailed.push);
sendMessagesToPeople.push(trySendMessageToPerson);
}
您可以定义传递给 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)