[英]Javascript: map asynchronous function over array, holding execution on each element until it returns on the previous one
I am trying to build a flashcard app, and I have two things: an array with data about each flashcard and an asynchronous function that takes in an element of the array and displays the flashcard to the user.我正在尝试构建一个抽认卡应用程序,我有两件事:一个包含每个抽认卡数据的数组和一个异步function,它接收数组的一个元素并向用户显示抽认卡。 As soon as the function is executed, the card is drawn on the screen.
只要执行 function,就会在屏幕上绘制卡片。
// not actual code, do not debug
const flashcards = [card1, card2, card3] // except way more cards
function showCard(card){
// immediately draws the card
// waits for user interaction
// returns a value when the user is done with the card
}
I want to loop over the cards in order, but I want only one card to show at a time.我想按顺序循环卡片,但我希望一次只显示一张卡片。 The problem is if I do this:
问题是如果我这样做:
// not actual code, do not debug
flashcards.forEach((item) => {
showCard(item)
})
...since the function is asynchronous, the browser displays all the flashcards at once, and they get all cluttered and unusable on the screen. ...由于 function 是异步的,浏览器会同时显示所有的抽认卡,它们在屏幕上变得杂乱无章且无法使用。
How can I loop over the cards in such a way that each card is drawn only after the user is done interacting with the previous card (ie, when showCard returns)?我怎样才能循环卡片,使得每张卡片只有在用户完成与前一张卡片的交互后才被绘制(即当 showCard 返回时)?
I don't think you're looking for an async solution but instead a flag to wait for user interaction.我认为您不是在寻找异步解决方案,而是在寻找等待用户交互的标志。
Something like:就像是:
let currentCardIndex = 0;
while (currentCardIndex < flashcards.length) {
showCard(flashcards[currentCardIndex]);
currentCardIndex++;
}
There are different approaches here you could either:这里有不同的方法,您可以:
Pseudocode for promise based solution基于 promise 的解决方案的伪代码
let aCardIsVisible = false
function onShowFlashcardHandler (cardId) {
// a card is already visible return
if (aCardIsVisible) {
return
}
const card = flashcards.find(card => card.id === cardId)
if (card) {
// toggle on flag
aCardIsVisible = true
showCard(card)
.then(value => {
// do something with return value
// toggle off flag
aCardIsVisible = false
})
}
}
function showCard (card) {
return new Promise((resolve) => {
// draw card
// on some UI input or timeout loop for checking UI changes
loop :=
if UI done then
value <- UI input value
resolve(value)
end
endloop
})
}
Pseudocode for callback based solution基于回调的解决方案的伪代码
let aCardIsVisible = false
function onShowFlashcardHandler (cardId) {
// a card is already visible return
if (aCardIsVisible) {
return
}
const card = flashcards.find(card => card.id === cardId)
if (card) {
// toggle on flag
aCardIsVisible = true
showCard(card, (value) => {
// do something with return value
// toggle off flag
aCardIsVisible = false
})
}
}
function showCard (card, callback) {
// draw card
// on some UI input or timeout loop for checking UI changes
loop :=
if UI done then
value <- UI input value
callback(value)
end
endloop
}
Pseudocode for event emitter or custom events based solution This assumes you either use a event emitter or custom events事件发射器或基于自定义事件的解决方案的伪代码假设您使用事件发射器或自定义事件
let aCardIsVisible = false
function onShowFlashcardHandler (cardId) {
// a card is already visible return
if (aCardIsVisible) {
return
}
const card = flashcards.find(card => card.id === cardId)
if (card) {
// toggle on flag
aCardIsVisible = true
showCard(card)
}
}
function onCardDone (value) {
// do something with return value
// toggle off flag
aCardIsVisible = false
}
function showCard (card) {
// draw card
// on some UI input or timeout loop for checking UI changes
loop :=
if UI done then
value <- UI input value
emitter.emit('cardDone', value) // event emitter
element.dispatchEvent('cardDone', value) // custom event
end
endloop
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.