redux-observables mergeMap w/ two outputs - redux-observable

I have an epic like this
/**
* Request a new account from the API
*/
export function signupApiRequest(action$: Observable, store: Store) {
return action$.ofType(SIGNUP)
.map(action => [ action, store.getState().accounts.signup ])
.mergeMap(([ action, signup ]) =>
sendCommand('/api/accounts/signup', {
name: signup.name,
email: signup.email
})
.map(response => [ response, signup.email ])
)
.mergeMap(([ response, email ]) => {
switch (response.status) {
case 409:
return [existingUser(email)];
case 201:
const succ = { type: successOf(SIGNUP) },
user = mapTokenToUser(response.body.data),
created = userCreated(user);
console.log('signup success', [succ, created]);
return [succ, created];
default:
throw new Error(`Unknown response code ${response.code}`);
}
});
}
When signing up, 'signup success' is printed and both actions are logged as they should.
However, only the first of the actions is outputted from the epic.
Why and what am I doing wrong?
Changing the order in the array makes the other value get outputted.

We've discovered this appears to be a bug in RxJS itself starting in 5.1.0. There's an exception being thrown in your reducer but it's being swallowed silently by RxJS.
https://github.com/redux-observable/redux-observable/issues/263#issuecomment-310180351
How it's interacting with redux/redux-observable is a little complicated, but ultimately not related as this can be reproduced with:
https://jsbin.com/dukixu/edit?html,js,output
const input$ = new Rx.Subject();
input$
.mergeMap(() => Rx.Observable.of(1, 2))
.subscribe(d => {
throw new Error('some error');
});
input$.next();

Related

mapPropertyErrors seems to only return null

I can't seem to get the automatic error messages working. My configuration seems to be correct from what I've read online, yet the error always get's picked up in the catch after using the repository.save(entity) function. I'm specifically trying to get an error related to leaving the field empty but :required="true" doesn't seem to help. Could it be because they are translation fields? My entity is called suiteseven_usp.
I've got the following definition:
protected function defineFields(): FieldCollection
{
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new Required(), new PrimaryKey()),
(new TranslatedField('text'))->addFlags(new ApiAware(), new Required()),
(new TranslatedField('subtext'))->addFlags(new ApiAware(), new Required()),
new StringField('icon', 'icon'),
new StringField('type', 'type'),
new TranslationsAssociationField(UspTranslationDefinition::class, 'suiteseven_usp_id'),
]);
}
The following in computed: in my component:
...mapPropertyErrors('suiteseven_usp', [
'text',
'subtext'
]),
And this as one of the fields:
<sw-field
v-model="usp.text"
class="s7-usp-detail__text"
:label="$tc('s7-usp.detail.fieldTextLabel')"
:placeholder="$tc('s7-usp.detail.fieldTextPlaceholder')"
:disabled="!acl.can('usp.editor')"
:error="suitesevenUspTextError"
:required="true"
></sw-field>
This is my save function:
onSave() {
this.isLoading = true;
this.isSaveSuccessful = false;
return this.uspRepository.save(this.usp, Shopware.Context.api).then(() => {
this.isSaveSuccessful = true;
this.createNotificationSuccess({
title: this.$tc('global.default.success'),
message: this.$tc('s7-usp.detail.notificationSuccessMessage'),
});
if (!this.uspId) {
this.$router.push({name: 's7.usp.detail', params: {id: this.usp.id}});
}
this.uspRepository.get(this.usp.id, Shopware.Context.api).then((updatedUsp) => {
this.usp = updatedUsp;
this.isLoading = false;
});
}).catch(() => {
this.createNotificationError({
title: this.$tc('global.default.error'),
message: this.$tc('s7-usp.detail.notificationErrorMessage'),
});
this.isLoading = false;
});
},
You also need to set Required flag to TranslationsAssociationField also.
(new TranslationsAssociationField(UspTranslationDefinition::class, 'suiteseven_usp_id'))->addFlags(new Required()),

Infinite loop with a graphql and mongoose backend

I have a backend made in express and mongoose:
all my mutations and queries work perfectly except one mutation sends me an infinite loader
updateVehicleVerification: async (_, { id, updateVehicleVerification }) => {
const vehicleVeri = await VehicleVerification.findById(id);
if (!vehicleVeri) {
throw new Error(ErrorMessage + ' : Verification de Vehicule');
}
await VehicleVerification.findByIdAndUpdate(
id,
updateVehicleVerification
);
const veri = await VehicleVerification.findById(id);
return veri;
},
and the query I use here:
export const UPDATE_CONTROL_VEHICLE = gqlmutation updateVehicleVerification( $id: String! $updateVehicleVerification: VerificationVehicleInput ) { updateVehicleVerification( id: $id updateVehicleVerification: $updateVehicleVerification ) { honk { state image comment } mileage dateVerification stateVehicle { damaged good missing } } };
enter code here
I I solved the problem !
I did not manage the case where the data reached me by the request which keyed an infinite loop.

React Native Possible Unhandled Promise Rejections Error

I'm using Agora to send a message through a data stream, it throws this error when I try to do so after changing to another channel (so from channel 1 and 2). Can anyone please help explain what this error means and how to solve it? I've been googling and I couldn't seem to find anything. Thanks a bunch!
Error: invalid argument
promiseMethodWrapper#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2275:45
sendStreamMessage#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:99747:47
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:98393:35
onPress#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:98579:46
onPress#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:68941:35
_performTransitionSideEffects#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:54979:22
_receiveSignal#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:54921:45
onResponderRelease#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:54830:34
invokeGuardedCallbackImpl#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:12804:21
invokeGuardedCallback#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:12898:42
invokeGuardedCallbackAndCatchFirstError#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:12902:36
executeDispatch#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:12974:48
executeDispatchesInOrder#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:12994:26
executeDispatchesAndRelease#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14069:35
forEach#[native code]
forEachAccumulated#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:13136:22
runEventsInBatch#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14093:27
runExtractedPluginEventsInBatch#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14172:25
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14148:42
batchedUpdates$1#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:24797:20
batchedUpdates#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14055:36
_receiveRootNodeIDEvent#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14147:23
receiveTouches#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:14200:34
__callFunction#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2798:36
http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2530:31
__guard#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2752:15
callFunctionReturnFlushedQueue#http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false:2529:21
callFunctionReturnFlushedQueue#[native code]
Edit:
Class
// States for buttons (touchable highlights).
state = {
micPressed: false,
dotMorsePressed: false,
dashMorsePressed: false,
channel1Pressed: false,
channel2Pressed: false,
};
componentDidMount() {
SplashScreen.hide();
this.init()
}
init = async () => {
// Initialize RtcEngine and event listeners.
engine = await RtcEngine.create('74a529c906e84fe8bfe4a236869b736f');
try {
dataStreamId = await engine.createDataStream(true, true);
} catch(error) {
console.log(error.message);
}
console.log("dataStream: ", dataStreamId);
Sound.setCategory('Playback');
beep = new Sound('beep.wav', Sound.MAIN_BUNDLE, (error) => {
if (error) {
console.log('failed to load the sound', error);
return;
}
})
engine.addListener('StreamMessage', (uid, streamId, data) => {
console.log('stream message was received: ', data, ' from: ', streamId )
receivedMorse = data;
console.log(receivedMorse);
if(receivedMorse == 'dot'){
beep.setCurrentTime(9.9);
beep.play();
} else {
beep.setCurrentTime(9.7);
beep.play();
}
})
engine.addListener('StreamMessageError', (uid, streamId, err, missed, cached) => {
console.log('StreamMessageError: ', err)
})
engine.addListener('JoinChannelSuccess', (channel, uid, elapsed) => {
console.log('channel was joined succesfully')
})
engine.addListener('LeaveChannel', (channel, uid, elapsed) => {
console.log('channel was left succesfully')
})
engine.addListener('Warning', (warn) => {
console.log('Warning', warn)
})
engine.addListener('Error', (err) => {
console.log('Error', err)
})
}
Functions:
// Functions.
micPressedFunc = () => {
// Function to enable microphone and mute speaker when mic button is pressed.
engine.adjustRecordingSignalVolume(100);
engine.adjustAudioMixingVolume(0);
};
micReleasedFunc = () => {
// Function to mute microphone and enable speaker when mic button is released.
engine.adjustRecordingSignalVolume(0);
engine.adjustAudioMixingVolume(100);
};
dotMorsePressedFunc = () => {
// Function to send dot to other users in the channel.
engine.sendStreamMessage(dataStreamId, 'dot');
beep.setCurrentTime(9.9);
beep.play();
};
dashMorsePressedFunc = () => {
// Function to send dash to other users in the channel.
engine.sendStreamMessage(dataStreamId, 'dash');
beep.setCurrentTime(9.7);
beep.play();
};
channel1PressedFunc = () => {
// Function to leave previous channel and join channel 1.
engine.leaveChannel();
engine.joinChannel(null, 'walt-channel-1', null, 0);
engine.adjustRecordingSignalVolume(0);
engine.adjustAudioMixingVolume(100);
isConnected = true;
this.setState({
channel1Pressed: true,
channel2Pressed: false,
});
};
channel2PressedFunc = () => {
// Function to leave previous channel and join channel 2.
engine.leaveChannel();
engine.joinChannel(null, 'walt-channel-2', null, 0);
engine.adjustRecordingSignalVolume(0);
engine.adjustAudioMixingVolume(100);
isConnected = true;
this.setState({
channel2Pressed: true,
channel1Pressed: false,
});
};
By looking at the documentation, it seems you are handling the events and order in the wrong way. The leave channel for example says this:
"After joining a channel, the user must call the leaveChannel method to end the call before joining another channel. This method returns 0 if the user leaves the channel and releases all resources related to the call. This method call is asynchronous, and the user has not exited the channel when the method call returns. Once the user leaves the channel, the SDK triggers the onLeaveChannel callback."
So basically, the user joining/leaving a channel is not immediate and you have to deal with those. I can't say the exact issue, but I can say that I don't think you are handling the lifecycle correctly.
At the very least, you can try to await the methods from the engine, but that alone might not be enough. You might need to leave the channel, then join the new one once you get confirmation.

Array being populated by itself

I'm having am issue with an array that seems to be getting populated with my mongoose code by itself. It's making it impossible to populate the array with modified values.
Here's the code:
router.get('/in-progress', function(req, res) {
console.log('exporting');
var dataset = [];
Intake.find({}, function(err, intakes) {
if(err){
console.log(err);
} else {
/*intakes.forEach(function(intake) {
dataset.push(
{
//requestName: intake.requestName,
requestName: 'Request Name',
status: intake.phase
}
)
});*/
return dataset;
}
}).then((dataset) => {
console.log(dataset);
const report = excel.buildExport(
[
{
heading: inProgressHeading,
specification: inProgressSpec,
data: dataset
}
]
);
res.attachment('requests-in-progress.xlsx');
return res.send(report);
});
});
As you can see, the logic to push data to "dataset" is commented out, but the console log is logging every Intake that I have in the MongoDB database. Does anyone know what I am doing wrong so that I can push my own values into "dataset"?

Angular 5 HTTPClient not returning results for RouteResolver

I have to say HttpClient Observables, subscriptions etc are pretty hard/time consuming to get right.
I have been working on a problem for a while now and tearing my hair out. I have a service that I need to be able to perform a mapping function on.
loadAllSummary(organisationId: number) {
return this.http.get('/api/aircrafts/organisations/' + organisationId)
.pipe(
map(data => data.forEach(datum => {
console.log('why am i not getting here! ' + JSON.stringify(data));
return this.mapToSummary(datum);
}))
);
}
with the mapToSummary() method:
private mapToSummary(aircraft: Aircraft): IAircraftSummary {
const lastDate: Date = new Date(Math.max.apply(null, aircraft.workorders.map(function(e) {
return new Date(e.date);
})));
return new AircraftSummary({
lastWork: lastDate,
rego: aircraft.registration,
make: aircraft.make,
model: aircraft.model,
contact: (aircraft.owner.type.endsWith('primary')) ? aircraft.owner.principal : aircraft.operator.principal,
phone: (aircraft.owner.type.endsWith('primary')) ? aircraft.owner.contact.phone : aircraft.operator.contact.phone
});
}
Now, I need these summaries as input data to a view, so I borrowed code from the interwebs and created this ResolverService:
#Injectable()
export class AircraftsResolverService implements Resolve<IAircraftSummary[]> {
constructor(private service: AircraftService,
private router: Router) { }
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<IAircraftSummary[]> {
console.log('called AircraftsResolverService')
const id = route.params['id'];
if (isNaN(+id)) {
console.log(`Organisation id was not a number: ${id}`);
this.router.navigate(['/login']);
return Observable.of(null);
}
return this.service.loadAllSummary(+id)
.map(summaries => {
console.log(summaries)
if (summaries) {
return summaries;
}
console.log(`Summaries were not found: ${id}`);
this.router.navigate(['/organisations/', +id]);
return null;
})
.catch(error => {
console.log(`Retrieval error: ${error}`);
this.router.navigate(['/organisations/', +id]);
return Observable.of(null);
});
}
}
Which I then refer to in the ngOnInit call...
ngOnInit() {
this.currentUser = this.authenticationService.returnCurrentUser();
this.route.data
.subscribe(({aircrafts}) => {
this.aircrafts = aircrafts;
const id = +this.route.snapshot.paramMap.get('id');
console.log(' where are my aircraft!' + JSON.stringify(aircrafts));
this.ELEMENT_DATA = aircrafts;
this.displayedColumns = ['Last Work', 'Rego', 'Make', 'Model', 'Contact', 'Phone'];
this.dataSource = new MatTableDataSource(this.ELEMENT_DATA);
this.dataSource.sort = this.sort;
console.log(id);
if (id) {
this.organisationService.getById(id).subscribe(org => {
this.organisation = org;
});
} else {
console.log('its bad');
}
});
console.log(this.dataSource);
}
The console log under the subscribe is undefined and the console.logs under the service never get triggered. So once again, I find myself not understanding why subscription fire or not fire, or whatever it is that they do.
How do I get past this? thanks everyone.
EDIT: appears that the problem is actually in the ResolverService, I have been able to determine that the data service is getting the results and that they are correct. For some reason, the resolver service can't see them.
The answer was in the route resolver, or rather the app-routing-module. I should have included it in the question, because some of the angular saltys would have picked it up
I was trying to do this:.
{ path: 'organisations/:orgId/aircrafts/:id', component: AircraftsComponent, resolve: {aircrafts : AircraftsResolverService}, canActivate: [AuthGuard] },
But you can't, you have to do this:
{ path: 'organisations/aircrafts/:orgId/:id', component: AircraftsComponent, resolve: {aircrafts : AircraftsResolverService}, canActivate: [AuthGuard] },
results in very non-resty urls, but, hey, whatever works, right?