Я работаю с приложением, где мне нужно вызвать HTTP-ответ на успех HTTP-вызова. Как мне реорганизовать мой код, чтобы избежать обратного вызова ада
Мой текущий код:
Component.ts
SomeFunction() {
const param2 = {ind_1: value_1, ind_2: value_2};
this.service.callFunction1(param)
.subscribe(
f1_res => {
if (f1_res.status === 'success' ) {
this.service.callFunction2(f1_res)
.subscribe(
f2_res => {
this.service.callFunction3(f2_res)
.subscribe(
f3_res => console.log('done', f3_res),
f3_err => console.log(err)
);
},
f2_err => console.log(f2_err)
)
}
},
f1_err => console.log(err)
);
}
И мой сервис - довольно стандартное угловое обслуживание
Service.ts
callFunction1(param) {
return this.http.post<any>( 'someurl.com', param );
}
callFunction2(param) {
return this.http.post<any>( 'someurl.com', param );
}
callFunction3(param) {
return this.http.post<any>( 'someurl.com', param );
}
Я понимаю, что это плохо, но как мне реорганизовать это?
Это простой пример для цепочки mergeMap
. Что-то вроде этого:
this.service.callFunction1(params).pipe(
mergeMap(res => this.service.callFunction2(res)),
mergeMap(res => this.service.callFunction3(res)),
)
.subscribe(
(result) => console.log('done', result),
(error) => console.log('error in chain', error),
);
Здесь работает Стакблитц.
Редактирование: конечно, вы можете обернуть те response.status === 'success'
в функции или прямо там, но если вы просто проверяете ошибки HTTP, все они просто сломают цепочку в этом обработчике ошибок в дно.
function doStuff(param) {
this.service.callFunction1(param)
.subscribe().then(step1(param)
.flatMap((step1Result) => step2(step1Result)
.flatMap((step2Result) => step3(step2Result))
.map((step3Result) => {
let doStuffResult = step3Result;
if (doStuffResult !== null) {
return doStuffResult;
}
})));
}
function step1(f1_res) {
let result: any = null;
this.service.callFunction1(f1_res)
.subscribe(res => {
if (res.status === 'success') {
// ...
this.result = res;
}
}, error => {
console.log(error);
});
return Rx.Observable.of(result);
}
function step2(f2_res) {
let result = null;
this.service.callFunction2(f2_res)
.subscribe(
f2_res => {
if (f2_res.status === 'success') {
this.result = f2_res;
}
}, error => { console.log(error) });
// ...
return Rx.Observable.of(result);
}
function step3(f3_res) {
let result = null;
this.service.callFunction2(f3_res)
.subscribe(
f3_res => {
this.result = f3_res;
}, error => { console.log(error) });
// ...
return Rx.Observable.of(result);
}
Один очень элегантный способ сделать это - дать каждому подписанный вызов как свою собственную единую ответственность и создать новый Observable
поэтому каждый из модулей по-прежнему ведет себя индивидуально, но они запускаются в цепочке.
вы можете немного уменьшить код с помощью операторов RxJS (у вас все еще есть обратные вызовы, хотя...).
например, ваш код может быть преобразован в нечто вроде этого:
SomeFunction() {
const param2 = {ind_1: value_1, ind_2: value_2};
this.service.callFunction1(param)
.flatMap(f1_res => f1_res.status === 'success' ? this.service.callFunction2(f1_res) : Observable.throw("f1 error"))
.flatMap(f2_res => this.service.callFunction3(f2_res))
.subscribe(
f3_res => console.log('done', f3_res),
error => console.error(error)
);
}