繁体   English   中英

Javascript:map 异步 function 在数组上,在每个元素上保持执行,直到它返回前一个元素

[英]Javascript: map asynchronous function over array, holding execution on each element until it returns on the previous one

我正在尝试构建一个抽认卡应用程序,我有两件事:一个包含每个抽认卡数据的数组和一个异步function,它接收数组的一个元素并向用户显示抽认卡。 只要执行 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
}

我想按顺序循环卡片,但我希望一次只显示一张卡片。 问题是如果我这样做:

// not actual code, do not debug

flashcards.forEach((item) => {
    showCard(item)
})

...由于 function 是异步的,浏览器会同时显示所有的抽认卡,它们在屏幕上变得杂乱无章且无法使用。

我怎样才能循环卡片,使得每张卡片只有在用户完成与前一张卡片的交互后才被绘制(即当 showCard 返回时)?

我认为您不是在寻找异步解决方案,而是在寻找等待用户交互的标志。

就像是:

let currentCardIndex = 0;

while (currentCardIndex < flashcards.length) {

    showCard(flashcards[currentCardIndex]);
    currentCardIndex++;
}

这里有不同的方法,您可以:

  1. 产生一个 promise 并等待使用 thenable 语义的返回值。
  2. 也传递一个回调,当用户完成 UI 时使用返回值调用
  3. 事件发射器发出卡已被处理并返回值。

Promise

基于 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
  })
}

打回来

基于回调的解决方案的伪代码


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
}

事件发射器或自定义事件

事件发射器或基于自定义事件的解决方案的伪代码假设您使用事件发射器自定义事件


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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM