Отклонить и прекратить обещание на внешнем событии

1

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

new Promise((resolve,reject)=>{
    websocket.onerror=reject;
    //do processing here
    websocket.onerror=undefined;
    resolve(...);
});

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

Использование async/wait выше не возможно вообще.

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

Теги:
asynchronous
promise

2 ответа

1
Лучший ответ

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

Это основное недоразумение (и вы не одиноки в этом!). Нет "остального обещания". Обещание - это просто средство наблюдения за завершением асинхронного процесса. Это процесс, а не обещание, продолжение.

Как вы отменяете этот процесс (и можете ли вы) полностью зависит от того, что этот процесс и обеспечивает ли он его отмену, что само по себе не связано с обещаниями. Кажется, вы используете веб-сокет, поэтому вам нужно будет использовать API-интерфейс веб-сокета, чтобы отменить все, что у вас есть (или отправить сообщение на другой конец, чтобы сообщить ему, чтобы он прекратил, что он делает).

Например: предположим, что обещание ожидало срабатывания таймера (setTimeout) и решило бы, когда это будет сделано. Затем происходит что-то другое, и вы больше этого не хотите. Отклонение обещания просто отвергает обещание, оно не оказывает никакого влияния на таймер. Вам также нужно отменить таймер (clearTimeout).


Повторите свое редактирование:

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

Нет, код в исполнителе обещаний (функция, которую вы передаете new Promise) запускается синхронно. Опять же, нет "остальной части кода" для отмены. Там могут быть асинхронные обратные вызовы или процесс, с которого начинается код, вам также нужно отправить отмену, но это не потребует сдачи каждой строки в ее собственном обещании, а вовсе не.

  • 0
    То есть событие никогда не сработает во время работы синхронного кода?
  • 0
    @ sunny-lan - событие может сработать, но обратный вызов для него будет находиться в очереди заданий до тех пор, пока текущее задание (выполнение синхронного кода в исполнителе обещаний) не будет завершено. Уже слишком поздно добавлять его к этому вопросу, но если вы не уверены, что отменить или где в своем реальном коде, я предлагаю опубликовать новый вопрос с минимальным воспроизводимым примером этого кода, показывающий реальные действия, которые вы делаете, так что люди могут помочь вам узнать, что, если что-то, нужно отменить в этом.
1

Понимание ответа на этот вопрос может помочь вам:

Когда вы создаете обещание, оно выполняется синхронно. Итак, эта строка выполнена:

websocket.onerror=reject;

На этом этапе ваш код начинает обрабатываться. Если есть событие ошибки websocket, оно помещается в цикл событий js, но ваше обещание все еще выполняется синхронно. Затем вы отвязываете обработчик ошибок websocket и разрешаете. Обещание будет разрешено, даже если произошла ошибка. На этом этапе вызов для решения также добавляется в js 'event loop. Затем выполняется следующий js tick, и, возможно, отклоняется, может быть, нет, но на данный момент это не имеет значения, потому что вы решили синхронно, и обещания никогда не меняют свое мнение после их разрешения или отклонения.

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

Чтобы отменить обещание, вам понадобятся некоторые довольно простые вещи, такие как

if(someOtherVariableThatDeterminesCancelation){
  reject()
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню