所以我有一个获取位置并返回承诺的函数。我将mobx用作商店来更新this.locationStoreProp
和this.hotel.subtext
属性。
public fetchPropertyLocation(some_input_params): Promise<any> {
return this.apiSource
.fetchPropertyLocationData(input)
.then(({ data }) => {
runInAction('update from response', () => {
if (data) {
this.locationStoreProp = data.location;
this.hotel.subtext = data.location.score;
}
});
})
.catch(error => {
runInAction('error in location', () => {
//log event
});
return {
error
};
});
}
现在,this.hotel
依赖于下面的另一个提取操作的问题。这需要在我的上述承诺之前解决,以便我可以在subtext
中设置this.hotel
。但是此fetchHotelInfo
函数在另一个fetch
(在它下面)中使用。
public fetchHotelInfo(input_params): Promise<any> {
return this.hotelInfoSource
.fetch(input)
.then(data => {
runInAction('update hotel from response', () => {
this.hotel = data;
});
return data;
})
.catch(error => {
runInAction('recovering from hotel info call failure', () => {
//log event
});
return {error};
});
}
public fetch(input_params) {
const { hotelId, searchCriteria } = this;
const infoPromise = this.fetchHotelInfo(input_params);
const someOtherPromise = this.someOtherOperation(input_params);
return Promise.all([infoPromise, someOtherPromise])
.then(
() =>
new Promise(resolve => {
runInAction('updating', () => {
this.isLoading = false;
resolve();
});
})
)
.catch(
() =>
new Promise(resolve => {
runInAction('updating hotel with failure', () => {
this.isFailure = true;
resolve();
});
})
);
}
最后,我很简单地等待着他们。我希望fetch
函数promise首先与它的fetchHotelInfo
promise一起解决,但是我的位置函数promise首先被解决,由于这个原因,我发现属性this.hotel
未定义。
public async fetch(options: FetchOptions): Promise<any> {
await fetchClassObj.fetch(params);
await fetchClassObj.fetchPropertyLocation(params);
}
这是怎么回事?谢谢。 另外,请不要担心语法。
答案 0 :(得分:1)
您将获得this.hotel
的未定义状态,因为在您的promise回调中,您正在通过另一个非承诺回调来调用函数runInAction
。承诺解决后,runInAction
仍处于待处理状态,尚未执行其回调。为了解决这个问题,我建议制作一个类似于以下的包装函数:
function runInActionPromise(status) {
return new Promise((res,rej) => {
runInAction(status,res);
});
}
当然,如果runInAction
是您定义的函数,则也可以将其编辑为使用promise而不是回调。
此外,您应该在代码中坚持使用async/await
或Promise.then()
,不要将两者混用。我建议使用async/await
来减少/消除似乎在您的代码中猖ramp的回调地狱。例如,您可以这样重写fetchPropertyLocation
:
public async fetchPropertyLocation(some_input_params): Promise<any> {
try {
let { data } = await this.apiSource.fetchPropertyLocationData(input);
await runInActionPromise('update from response');
this.locationStoreProp = data.location;
this.hotel.subtext = data.location.score;
} catch(error) {
await runInActionPromise('error in location');
//log event
return {error};
}
}
和fetchHotelInfo
这样:
public async fetchHotelInfo(input_params): Promise<any> {
try {
let data = await this.hotelInfoSource.fetch(input);
await runInAction('update hotel from response');
this.hotel = data;
return data;
} catch(error) {
await runInAction('recovering from hotel info call failure');
return {error};
}
}
这明显更具可读性,您甚至可以对try/catch
使用“同步”错误处理。
无论采用哪种方式,只要您确保在runInAction
中通过在每个使用它的地方都用promise包住回调来解决回调问题,
答案 1 :(得分:0)
您如何做这样的事情:
未经测试
fetchHotelInfo().then(hotel => {
this.hotel = hotel;
return fetchPropertyLocation();
}).then(propertyLocation => {
this.hotel.prop = propertyLocation.prop;
this.hotel.bar = propertyLocation.bar;
});
像这样,您不必混合使用async/await
和Promises
,而且看起来也很整洁。由于Promises
在某种程度上旨在替代callbacks
,因此,如果您也将runInAction
函数也转换为一个函数,那就很好了。
所以:
function runInAction(): Promise<void> {
return new Promise(...);
}
.catch(() => runInAction('updating hotel with failure'));
作为副作用,这将防止链断裂,并使整个代码看起来更加一致。
重要:如果您在此类链的中间使用回调,则会中断执行代码的顺序。因此,请勿在promise中使用回调(除非其中包含resolve()
)。