Javascript: сопоставить асинхронную функцию с массивом, удерживая выполнение для каждого элемента, пока он не вернется к предыдущему - PullRequest
1 голос
/ 10 июля 2020

Я пытаюсь создать приложение для карточек, и у меня есть две вещи: массив с данными о каждой карточке и асинхронная функция, которая принимает элемент массива и отображает карточку пользователю. . Как только функция будет выполнена, карта отобразится на экране.

// 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
}

Я хочу l oop по порядку, но я хочу, чтобы отображалась только одна карта. Проблема в том, что я сделаю это:

// not actual code, do not debug

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

... поскольку функция является асинхронной, браузер отображает все карточки сразу, и все они загромождены и непригодны для использования на экране.

Как я могу oop перекрыть карты таким образом, чтобы каждая карта вытягивалась только после того, как пользователь завершил взаимодействие с предыдущей картой (то есть, когда showCard вернется)?

Ответы [ 2 ]

0 голосов
/ 10 июля 2020

Здесь есть разные подходы, вы можете:

  1. Создать обещание и дождаться возвращаемого значения от использования доступной семантики.
  2. Также передать обратный вызов, который вызывает с возвратом значение, когда пользователь завершил работу с пользовательским интерфейсом
  3. Генератор событий, чтобы сообщить, что карта была обработана с возвращаемым значением.

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
}


0 голосов
/ 10 июля 2020

Я не думаю, что вы ищете решение asyn c, а вместо этого флаг для ожидания взаимодействия с пользователем.

Что-то вроде:

let currentCardIndex = 0;

while (currentCardIndex < flashcards.length) {

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

...