Однако теперь я могу понять, почему reader.read является ожидаемым, а writer.write - нет?Поскольку они обе являются операциями ввода-вывода, метод записи также должен быть приемлемым, верно?
Не обязательно.Фундаментальная асимметрия между read()
и write()
заключается в том, что read()
должен возвращать фактические данные, тогда как write()
действует исключительно из-за побочного эффекта.Так что read()
должен быть ожидаемым, потому что он должен приостановить вызывающую сопрограмму, когда данные еще не доступны.С другой стороны, write()
может быть (и в асинхронном режиме) реализован путем сохранения данных в некотором буфере и планирования их записи в подходящее время.
У этого плана есть важные последствия, такие какзапись данных быстрее, чем читает другая сторона, вызывает переполнение буфера без границ, а исключения во время write()
фактически теряются.Обе проблемы устраняются путем вызова writer.drain()
, который применяет противодавление , т.е. записывает буфер в ОС, при необходимости приостанавливая сопрограмму в процессе.Это делается до тех пор, пока размер буфера не опустится ниже порога .В документации write()
указано, что «после вызовов write()
следует drain()
».
Отсутствие противодавления в write()
является результатом реализации асинхронных потоков поверх callback-основанный слой, в котором не асинхронный write()
гораздо удобнее использовать, чем полностью асинхронная альтернатива.См. статью Натаниэля Дж. Смита , автора trio , для подробного рассмотрения темы.