Совет: используйте только first()если:
- Вы считаете, что ноль отправленных элементов является условием ошибки (например, завершение перед отправкой) И если вероятность ошибки больше 0%, вы правильно ее обрабатываете
- ИЛИ Вы на 100% знаете, что наблюдаемый источник испускает 1+ элементов (поэтому никогда не может выбросить) .
Если выбросы нулевые и вы явно не обрабатываете их (с помощью catchError), то эта ошибка будет распространяться вверх, возможно, вызовет неожиданную проблему в другом месте, и ее может быть довольно сложно отследить, особенно если она исходит от конечного пользователя.
По большей части вы безопаснее использовать take(1)при условии, что:
- Вы в порядке,
take(1)если ничего не испускаете, если источник завершается без эмиссии.
- Вам не нужно использовать встроенный предикат (например
first(x => x > 10)).
Примечание: Вы можете использовать предикат с take(1)так: .pipe( filter(x => x > 10), take(1) ). Это не приведет к ошибке, если ничто не превышает 10.
Что о single()
Если вы хотите быть еще строже и запретить два выброса, вы можете использовать single()какие ошибки, если выбросы равны нулю или 2+ . В этом случае вам снова придется обрабатывать ошибки.
Совет: Singleиногда может быть полезен, если вы хотите, чтобы ваша наблюдаемая цепочка не выполняла лишнюю работу, например, дважды вызывала http-службу и генерировала две наблюдаемые. Добавление singleна конец трубы сообщит вам, если вы сделали такую ошибку. Я использую его в «средстве выполнения задач», где вы передаете наблюдаемую задачу, которая должна выдавать только одно значение, поэтому я передаю ответ, single(), catchError()чтобы гарантировать хорошее поведение.
Почему бы всегда не использовать first()вместо take(1)?
ака. Как first потенциально может вызвать больше ошибок?
Если у вас есть наблюдаемый объект, который берет что-то из службы, а затем передает это по first()конвейеру, в большинстве случаев все будет в порядке. Но если кто-то по какой-то причине придет и отключит службу - и изменит ее на emit, of(null)иначе NEVERлюбые последующие first()операторы начнут выдавать ошибки.
Теперь я понимаю, что это может быть именно то , что вам нужно, поэтому это всего лишь подсказка. Оператор firstобратился ко мне, потому что это звучало немного менее «неуклюже», чем, take(1)но вам нужно быть осторожным с обработкой ошибок, если когда-либо есть вероятность того, что источник не будет излучать. Однако все будет зависеть от того, что вы делаете.
Если у вас есть значение по умолчанию (константа):
Также .pipe(defaultIfEmpty(42), first())подумайте, есть ли у вас значение по умолчанию, которое следует использовать, если ничего не испускается. Это, конечно, не вызовет ошибку, потому firstчто всегда будет получать значение.
Обратите внимание, что defaultIfEmptyзапускается только в том случае, если поток пуст, а не в том случае, если значение того, что испускается, равно null.
first()иtake()в целом они такие же, что я думаю, очевидно, только то, чтоfirst()иtake(1)такие же. Я не уверен в вашем ответе, считаете ли вы, что разница все еще есть?