Nano Hash - криптовалюты, майнинг, программирование

Разрешить ждать, когда придет сообщение

У меня есть код веб-сокета в JS. У меня есть такой цикл обработки сообщений:

socket.addEventListener('message', function (event) {
  payload = JSON.parse(event.data)
  method = payload.method
  // Dispatch messages
  if (method == 'cmd1') { 
    handle_cmd1(payload);  // trigger event/semaphore here to wait up waiter
  }
  else if (method == 'cmd2') { ... }
});

И в другом месте у меня есть обратный вызов кнопки, подобный этому:

$('#my-button').change(function() {
  handle_button();
});
async function handle_button() {
  send_msg('msg1', 'hi');
  // wait for server to reply with cmd1
  cmd1_data = await something(); // what?
  alert(`cmd1 data: $(cmd1_data)`);
}

Идея состоит в том, что кнопка отправляет «msg1», а сервер должен ответить «cmd1» и некоторой информацией. Я хочу дождаться этого ответа, а затем сделать еще кое-что. Итак, мой вопрос: как их заблокировать? В С++ я бы использовал семафор. Я бы предпочел не вращать петлю; есть ли что-то в Javascript/JQuery, которое я могу использовать для запуска, а затем ждать пользовательского события, подобного этому? Я новичок в JS и очень новичок в JS async/await.

РЕДАКТИРОВАТЬ: я сделал простой jsfiddle, чтобы показать, что мне нужно. http://jsfiddle.net/xpvt214o/484700/


  • Я думаю, что вы можете решить это обещанием 25.07.2018
  • Где определяется send_msg? Вы могли бы вернуть обещание возвращаемого сообщения (разрешение обещания, когда сокет возвращает сообщение). Затем вы можете использовать cmd1_data = await send_msg('msg1', 'hi'); 25.07.2018
  • Похоже, вам нужно будет зарегистрировать очередь слушателей на вашем сокете. 25.07.2018
  • @HereticMonkey: сейчас send_msg — это просто socket.send(JSON.stringify({'method': method, 'params': params}));, где сокет — это WebSocket. Я был бы счастлив, если бы он вернул обещание для ответного сообщения, но это та же проблема: что выполняет это обещание? Как мне уведомить об этом обещании из моего цикла обработчика сообщений? 25.07.2018
  • Реализуйте EventEmitter для своего сокета, вы можете сделать что-то вроде await new Promise(res => methods.once("cmd1", res)); 25.07.2018
  • Итак, как уже упоминалось, вы, вероятно, захотите реализовать что-то, что отслеживает эти сообщения по мере их перемещения. EventEmitter является популярным шаблоном для этого, как и шаблон pub/sub или Observer. По сути, это отдельный объект, который отправляет сообщения и ожидает ответа, позволяя другим функциям уведомляться о получении ответа. 25.07.2018
  • Хорошо, я понимаю шаблон EventEmitter: я регистрирую обработчик для ответного сообщения, и когда оно приходит, этот обработчик вызывается. Но тогда что? Как этот обработчик разрешает исходное обещание, которое ожидает handle_button? Может быть, мне просто нужно прочитать об обещаниях. Мне кажется, что они могут быть разрешены только из функции обещания. Если я сделаю обещание глобальным, в нем, например, не будет никакого метода myPromise.resolve(). 25.07.2018
  • Я добавил jsfiddle с упрощенным примером того, что мне нужно. Нажмите кнопку 1, чтобы начать ожидание, затем нажмите кнопку 2, чтобы сообщить коду кнопки 1 о продолжении. Но часть семафора — это просто комментарии, потому что я не знаю, как это сделать в js. 25.07.2018
  • Другой способ спросить: какие вещи может ожидать функция Promise без блокировки? Ввод/вывод, тайм-аут... что еще, если что? 25.07.2018

Ответы:


1

something() должен быть методом, который возвращает обещание(), или должен быть другим методом, который также помечен как async.

function something(){
  return new Promise(resolve,reject) {
      //... call your database
      // then
      resolve(theResult)
      // or
      reject(theError)
  }
}

Асинхронность и ожидание по большей части являются просто обертками вокруг промисов. Ожидание возвращается, когда обещание вызывает разрешение, и выдает исключение, когда обещание вызывает отклонение.

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

25.07.2018
  • Хорошо, но как мне получить код в обработчике цикла событий (handle_cmd1) для выполнения этого обещания? 25.07.2018

  • 2

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

    wakeup = null;
    
    // returns a promise that will be resolved by calling wakeup()
    // (could be a list of these or whatever, this is just a simple demo)
    function wakeable() {
        return new Promise( (resolve) => {
            wakeup = () => { resolve(true); }
        });
    }
    
    // demo of waiting and getting woken up:
    async function handle_event() {
        while (true) {
            console.log("waiting...")
            await wakeable(); // returns to event loop here
            console.log("handle event woke up!");
        }
    }
    
    handle_event(); // start in "background"
    wakeup(); // wake it up
    setTimeout(_ => { wakeup(); }, 500); // wake it up again after a delay
    

    Здесь происходит то, что когда вы вызываете wakeable(), он возвращает обещание. Это обещание создано с помощью анонимной функции (той, которая принимает resolve в качестве аргумента); конструктор обещания синхронно вызывает эту функцию, передавая ей метод разрешения обещания. В нашем случае функция устанавливает wakeup в другую анонимную функцию, которая вызывает исходную resolve; это закрытие, поэтому у него есть доступ к этой функции разрешения, даже когда она вызывается позже. Затем он возвращает новое обещание.

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

    Обещание разрешается, когда вызывается его функция разрешения; в этом случае вызов wakeup() вызывает внутренний метод resolve() обещания, который запускает любые методы .then на следующем тике цикла событий Javascript (используя очередь обещаний, упомянутую выше). Здесь мы используем await, но .then(...) будет работать так же.

    Так что нет никакого волшебства; Обещания ввода-вывода и тайм-аута работают одинаково. Они ведут закрытый реестр функций, которые вызываются, когда происходит событие ввода-вывода или тайм-аут, и эти функции вызывают функцию resolve() обещания, которая запускает .then() или удовлетворяет await.

    Между прочим, в отличие от асинхронности в python, оставлять отложенное обещание «открытым» при завершении процесса в Javascript вполне нормально, и на самом деле эта демонстрация делает это. Он завершается, когда больше нет кода для запуска; тот факт, что цикл while все еще «ожидает», не поддерживает выполнение процесса, потому что на самом деле это просто некоторые замыкания, хранящиеся в очереди. Цикл событий пуст, поэтому процесс завершается (при условии, что он находится в node.js — в браузере он просто возвращается к ожиданию событий).

    14.08.2018
    Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..