Теперь, когда я понимаю, как работают промисы в 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
handle_cmd1
) для выполнения этого обещания? 25.07.2018