Problem: callback hell (回调地狱)
指的是多层回调导致代码可读性变差。
特点:嵌套的多层括号。
async saveAndUpdateStudyState(state: ProcessState): Promise<any> {
return new Promise((resolve, reject) => {
if (this.isValidToSave) {
if (this.lastPatientExternalIdStashed && this.lastStudyIdStashed) {
const queryStudyLocal: StudyForEditorLocalStashMeta = JSON.parse(
this.localStoreService.query(this.lastStudyIdStashed)
);
const queryPatientLocal: PatientForEditorLocalStashMeta = JSON.parse(
this.localStoreService.query(queryStudyLocal.data.data.patient_id)
);
console.log('in update', queryStudyLocal);
upsertInRemoteDB(
this.patientService,
queryPatientLocal.data,
(x: Patient[]) => {
if (x && x.length > 0)
this.localStoreService.update(x[0].id, {
...queryPatientLocal,
data: x[0]
});
else reject('failed to query patient in remote DB');
upsertInRemoteDB(
this.studyService,
toState(queryStudyLocal, state).data,
(x: Study[]) => {
if (x && x.length > 0)
this.localStoreService.update(x[0].id, {
...queryStudyLocal,
data: x[0]
});
else reject('failed to query study in remote DB');
console.log('on refetched study', x);
resolve(x[0]);
}
);
}
);
}
} else {
console.log('not valid data');
reject('not valid data');
}
});
}
after fixed:
upsertInRemoteDB
async function upsertInRemoteDB<T extends { id: string }>(
service: {
updateMany: (...data: T[]) => Observable<T[]>;
createMany: (...data: T[]) => Observable<T[]>;
queryMany: (...data: string[]) => Observable<T[]>;
},
data: T
): Promise<any> {
const queryResult = await service.queryMany(data.id).toPromise();
return queryResult.length === 0
? await service.createMany(data).toPromise()
: await service.updateMany(data).toPromise();
}
isValidToUpdateStudyState
isValidToUpdateStudyState() {
if (
this.isValidToSave &&
this.lastPatientExternalIdStashed &&
this.lastStudyIdStashed
) {
const queryStudyLocal: StudyForEditorLocalStashMeta = JSON.parse(
this.localStoreService.query(this.lastStudyIdStashed)
);
const queryPatientLocal: PatientForEditorLocalStashMeta = JSON.parse(
this.localStoreService.query(queryStudyLocal.data.data.patient_id)
);
console.log('in update', queryStudyLocal);
if (queryPatientLocal && queryStudyLocal)
return { localStudy: queryStudyLocal, localPatient: queryPatientLocal };
else throw Error('fail to query study or patient in local');
} else throw Error('not valid data');
}
saveAndUpdateStudyState
async saveAndUpdateStudyState(state: ProcessState): Promise<any> {
const data: {
localStudy: StudyForEditorLocalStashMeta;
localPatient: PatientForEditorLocalStashMeta;
} = this.isValidToUpdateStudyState();
const remoteResultOfPatient = await upsertInRemoteDB(
this.patientService,
data.localPatient.data
);
if (remoteResultOfPatient) {
const remoteResultOfStudy = await upsertInRemoteDB(
this.studyService,
toState(data.localStudy, state).data
);
if (remoteResultOfStudy) return remoteResultOfStudy;
else throw Error('study upsert failed.');
} else throw Error('patient upsert failed.');
}
代码优化的方式:
1,同步异步代码分离,涉及到promise的地方用await关键字优化。
2,尽量不要混用几种异步方式,例如这里用promise那么upsertInRemoteDB函数也应该返回promise的形式。
异步的三种方式:
1,callback
definition:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
Reference:https://baike.baidu.com/item/%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0/7545973?fr=aladdin
2,promise:
eg: ajax发送http请求
var ajax = ajaxGet('http://...');
ajax.ifSuccess(success)
.ifFail(fail);
这种链式写法的好处在于,先统一执行AJAX逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调用success
函数或fail
函数。
古人云:“君子一诺千金”,这种“承诺将来会执行”的对象在JavaScript中称为Promise对象。
Reference:https://www.liaoxuefeng.com/wiki/1022910821149312/1023024413276544
3,Observable:
一种基于观察者模式的异步模型。
ReactiveX(Rx)是一种结合了observable模式、FP(functional programming)、iterator模式的一种优秀的开源实现。
Reference:http://reactivex.io/