Я работаю над относительно простым приложением, в котором хочу узнать больше о ngrx, redux и angular 2.
Я кратко объясню настройку моего приложения, моего appstate и редукторов.
В моем приложении я хочу рисовать определенные объекты (сетки) на моем экране с помощью фреймворка webgl. Я хочу добавить сетку через хранилище ngrx, создав простые объекты со свойствами этих сеток и сохраняя их в состоянии приложения. Всякий раз, когда добавляется «сетка», я хочу использовать побочные эффекты ngrx, чтобы рисовать сетку на экране с помощью службы, которая имеет доступ к структуре webgl.
Мое (упрощенное) приложение выглядит так:
export interface AppState {
meshList: MeshListReducer.MeshListState
}
Чтобы добавить сетку, я создал следующие функции редуктора:
case MeshActions.ADD_MESH: {
return Object.assign({
entities: [meshAction.payload, ...state.entities]
});
}
case MeshActions.ADD_MESH_SUCCESS:
case MeshActions.UPDATE_MESH: {
// This reducer function is only being called once, see below for further explanation.
return Object.assign({}, state, {
entities: state.entities.map(meshItem => {
// If we can find a mesh with this id, use the sub reducer to update it.
if (meshItem.uuid === meshAction.payload.uuid)
return meshSubReducer(meshItem, meshAction);
return meshItem;
})
});
}
default: {
return state;
}
}
export function meshSubReducer(mesh: BaseMesh, meshAction: MeshAction): BaseMesh {
switch (meshAction.type) {
case MeshActions.ADD_MESH_SUCCESS:
case MeshActions.UPDATE_MESH:
return Object.assign({}, meshAction.payload);
default:
return mesh;
}
}
И, наконец, мой класс эффектов, который содержит вызов службы фреймворка webgl и вызов действия success:
@Effect()
addMesh$ = this.actions$
.ofType(MeshActions.ADD_MESH)
.map((action: MeshAction) => action.payload)
.switchMap((payload: BaseMesh) => this._worldService.addMeshToWorld(payload))
.map(payload => this._meshActions.addMeshSuccess(payload));
И функция worldService.addMeshToWorld:
public addMeshToWorld(mesh: BaseMesh): Promise<BaseMesh> {
let p = new Promise<BaseMesh>((resolve, reject) => {
let renderer = this._meshRendererFactory.createMeshRenderer(mesh);
// Every call to the ngrx effects always enters this function, and the component is sucessfully added to the canvas.
renderer.addTo(this._world.app).then((component: WHS.Component) => {
resolve(Object.assign({}, mesh, {
rendererId: (<any>component).native.id
}));
});
});
return p;
}
И я вызываю все эти функции, используя следующие методы отправки:
let soccerBall = new SphereMesh({
geometry: {
heightSegments: 20,
widthSegments: 20,
radius: 5
},
gameMeshType: Enums.GameMeshType.Sphere,
uuid: this._meshHelper.generateUUID(),
meshMaterial: {
color: 0xF2F2F2
}
});
let soccerBall2 = new SphereMesh({
geometry: {
heightSegments: 20,
widthSegments: 20,
radius: 5
},
gameMeshType: Enums.GameMeshType.Sphere,
uuid: this._meshHelper.generateUUID(),
meshMaterial: {
color: 0xF2F2F2
}
});
// Dispatching these straight after each other will cause the succes action to only be dispatched once.
this._store.dispatch(this._meshActions.addMesh(soccerBall));
this._store.dispatch(this._meshActions.addMesh(soccerBall2));
Проблема, с которой я столкнулся, заключается в том, что после вызова побочного эффекта «ADD_MESH» и после добавления сетки на экран эффект вызывает только последнее действие «карта» только один раз, поэтому функция редуктора ADD_MESH_SUCCES вызывается только для одной сетки. , а не другой, см. снимок экрана:
Странно то, что, когда я добавляю вторую отправку в тайм-аут, успешный вызов теперь внезапно вызывается правильно для всех отправленных элементов:
this._store.dispatch(this._meshActions.addMesh(soccerBall));
setTimeout(() => {
// Now succes action is suddenly being called twice like it should..
this._store.dispatch(this._meshActions.addMesh(soccerBall2));
}, 1500);
Что могло вызвать такое странное поведение? Я думал, что мое приложение было довольно простым, но мне кажется, что мне чего-то не хватает.
Я использую следующие версии пакетов (я выбрал пакеты, которые, на мой взгляд, было бы наиболее полезно упомянуть здесь:
"@angular/core": "^5.0.0",
"rxjs": "^5.5.2",
"@ngrx/effects": "^5.2.0",
"@ngrx/store": "^5.0.0",
"typescript": "~2.4.2"