Javascript 承诺不同步解决,尽管等待

Javascript 承诺不同步解决,尽管等待,javascript,ecmascript-6,promise,mobx,mobx-react,Javascript,Ecmascript 6,Promise,Mobx,Mobx React,所以我有一个函数,它获取位置并返回一个承诺。我使用mobx作为一个商店,在这里我更新了this.locationStoreProp和this.hotel.subtext属性 public fetchPropertyLocation(some_input_params): Promise<any> { return this.apiSource .fetchPropertyLocationData(input) .then(({ data }) =&g

所以我有一个函数,它获取位置并返回一个承诺。我使用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
        };
      });
  }

最后,我简单地等待着他们。我希望
fetch
函数promise首先用
fetchHotelInfo
promise解析,但我的位置函数promise首先解析,因此我发现属性
this.hotel
未定义

public async fetch(options: FetchOptions): Promise<any> {
 await fetchClassObj.fetch(params);
 await fetchClassObj.fetchPropertyLocation(params);
}
公共异步获取(选项:获取选项):承诺{ 等待fetchClassObj.fetch(参数); 等待fetchClassObj.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};
  }
}
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};
  }
}
未经测试

这样你就不必混合使用
async/await
Promises
,而且一切看起来都很整洁。因为
承诺
在某种程度上是为了替换
回调
而设计的,所以如果您也将
运行不活动
函数转换为一个函数,那就太好了

因此:

函数runInAction():Promise{
返回新承诺(…);
}
.catch(()=>runInAction('updateinghotelwithfailure');
作为一个副作用,这将防止链条断裂,并使整个代码看起来更加一致


<强>重要< /强>如果在这样一个链的中间使用回调,它将破坏代码执行的顺序。所以不要在承诺中使用回调(除非回调中包含

resolve()

您得到的
this.hotel
是未定义的,因为在承诺回调中,您使用另一个非承诺回调调用函数
runInAction
。当承诺解析时,
runInAction
仍处于挂起状态,尚未执行其回调。为了解决这个问题,我建议创建一个类似以下内容的包装函数:

function runInActionPromise(status) {
  return new Promise((res,rej) => {
    runInAction(status,res);
  });
}
当然,如果
runInAction
是您定义的函数,您也可以编辑它以使用承诺而不是回调

此外,您应该在代码中坚持使用
async/await
Promise.then()
,而不是两者兼而有之。我建议
async/await
减少/消除代码中似乎猖獗的回调地狱。例如,您可以这样重写
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};
  }
}
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
中对回调进行说明,并在您使用它的任何地方使用一个承诺,那么它最终都会起作用。

您为什么要将
wait
混合使用呢?只需使用其中一个,我需要更新
中的一些变量,然后
等待fetchClassObj.fetch(params)。然后(()=>fetchClassObj.fetchPropertyLocation(params))降低5个缩进级别,以这种方式使用承诺,实际上是对承诺意图的嘲弄!使用
async/await
并去掉那些丑陋的回调树!还有一个问题是,每次使用
runInAction
,您都会将承诺与旧式回调混为一谈,它将承诺的全部点丢到窗口之外,除非你把它封装在<代码>新承诺中,正如你在<代码> FETCH runInAction
的回调将在稍后某个时候执行,这正是使用承诺的时间-因此您可以捕获该结果并将其与其余异步结果一起显示。更改了answer@Elias你能给我指出一些好的资源来澄清我的观点吗?谢谢。当然,但是如果你知道承诺,没有什么能阻止你。只需开始使用一个API。它使一切更具可读性。如果您有任何问题,请询问更具体的问题。《承诺》总是一本好书。谢谢。但是
runInAction
不是我定义的。这是
mobx
api方法。另外,你能给我指一些好的资源来澄清我关于这方面的概念吗?谢谢
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};
  }
}
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};
  }
}