Конечная цель
У меня есть метод регистрации пользователя/устройства. В нем мне нужно:
Где я нахожусь
Во время сборки и для простоты я не занимался токенизацией. Я работал только с deviceId, и нижеприведенное работало/работает отлично.
Я вызываю вспомогательный метод isStorageReady, проверяю ответ, затем вызываю вспомогательный метод getDeviceId и проверяю этот ответ.
this.isStorageReadyAsync()
.pipe(
map(storageResponse => {
// check storageResponse
// if undefined throw error
// error picked up by retryPipeline
// if retryPipeline exhausted picked up
// by errorPipeline and stream is stopped
if (storageRes === undefined ||
storageRes['LOCALSTORAGE'] === undefined ||
storageRes['LOCALSTORAGE'] === '') throw 'storageRes or
storageRes.LOCALSTORAGE are undefined or empty';
}),
flatMap(_ => this.getStoredDeviceIdAsync()),
map(deviceId => {
return iif (() => deviceId === undefined ||
deviceId === null ||
deviceId === '',
// no deviceId stored on device
// register device to get deviceId
this.registerDeviceAsync(),
// deviceId found in local storage
of({id: deviceId, new: false}))
}),
this.storeDeviceIdPipeline, // store deviceId
this.retryPipeline, // retry if e.g. experiencing network issues
this.errorPipeline // catch and handle errors
)
Где я застрял
У меня есть второй вспомогательный метод, getStoredTokenAsync()
, который я хотел бы вызывать параллельно с getStoredDeviceIdAsync()
. Я пробовал использовать forkJoin
и передавать массив в следующий за ним оператор map
, но моему машинописному линтеру это совсем не нравится. Все, что предшествует forkJoin, подчеркивается, как если бы это было ошибкой, и ошибка выглядит следующим образом:
Argument of type OperatorFunction is not assignable to parameter of type OperatorFunction. Type void is not assignable to type {}.
Так что я не совсем понимаю. Я надеялся использовать что-то вроде этого:
...
forkJoin([this.getStoredDeviceIdAsync(), this.getStoredTokenAsync()]),
map(authArr => {
let deviceId = authArr[0];
let token = authArr[1];
...
})
...
Если нет ошибки, он просто возвращает наблюдаемое, переданное ему. Возможно, не лучший/самый декларативный способ построить его с моей стороны. Таким образом, карта просто проверяет наличие ошибки и выдает ее. Если ошибки нет, то карта ничего не делает.
Проверка на наличие ошибок на карте - это нормально. В любом случае она должна что-то вернуть ( storageResponse ) или показать подчеркивание.
Тип void, вероятно, является картой. Я предлагаю вам использовать оператор flatMapTo, чтобы объявить, что вы не заинтересованы в предыдущем вводе
Ах! Возврат storageResponse действительно решает первую проблему. Спасибо. Не слышал о flatMapTo. Где документация на него? Что-то гуглю и не могу найти. Кроме того, какие-либо сведения об использовании forkJoin для параллельного запуска двух вспомогательных методов?
Если сами вспомогательные методы возвращают наблюдаемый объект, вы можете сохранить их в массив, как писали ранее. Просто не используйте forkjoin непосредственно внутри канала, так как forkjoin не является оператором. сопоставьте его с помощью операторов слияния/исчерпания/переключателя/concatMap
С помощью forkJoin
вы можете направить оба потока внутрь forkJoin
и map
, как обычно. flatMap
теперь называется mergeMap
Милая! Встраивание forkJoin
внутрь mergeMapTo
отлично работает!
Спасибо обоим комментаторам, LookForAngular и Юлиусу Дзидзявичюсу, за помощь в составлении! Я предоставляю полный ответ здесь, если это полезно для других. Также предоставление большего количества кода для некоторого дополнительного контекста.
Перед вызовом mergeMapTo
выполняется некоторая общая проверка ответа. Результат этого не потребляется, поэтому использование mergeMapTo
уместно (подразумевается, что все, что было до этого, не имеет отношения к тому, что происходит внутри mergeMapTo
).
mergeMap
существенно сглаживает внутреннюю наблюдаемую, которая обеспечивается моим вызовом iif
. Вывод из mergeMap
направляется в мой конвейер хранилища (это просто вызов map
), который обрабатывает всю логику, связанную с аутентификацией пользователя и т. д.
pipe(
...
mergeMapTo(forkJoin([this.getStoredDeviceIdAsync(), this.getStoredTokenAsync()])),
mergeMap(authArr => {
let deviceId = authArr[0];
let token = authArr[1];
return iif (() => deviceId === undefined || deviceId === null || deviceId === '' ||
token === undefined || token === null || token === '',
this.registerDeviceAsync(), // register device to get deviceId and token
of({deviceId: deviceId, token: token, new: false}))
}),
this.storeDeviceIdTokenPipeline,
this._config.retryPipeline, // generic retryWhen procedure
this._config.errorPipeline // generic catchError procedure
)
Карта в третьей строке что-то возвращает? Я вижу бросок, но не возвращаемое значение