尽管等待着他们,但他们仍然无法同步解决

时间:2019-11-26 16:51:14

标签: javascript ecmascript-6 promise mobx mobx-react

所以我有一个获取位置并返回承诺的函数。我将mobx用作商店来更新this.locationStorePropthis.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);
}

这是怎么回事?谢谢。 另外,请不要担心语法。

2 个答案:

答案 0 :(得分:1)

您将获得this.hotel的未定义状态,因为在您的promise回调中,您正在通过另一个非承诺回调来调用函数runInAction。承诺解决后,runInAction仍处于待处理状态,尚未执行其回调。为了解决这个问题,我建议制作一个类似于以下的包装函数:

function runInActionPromise(status) {
  return new Promise((res,rej) => {
    runInAction(status,res);
  });
}

当然,如果runInAction是您定义的函数,则也可以将其编辑为使用promise而不是回调。

此外,您应该在代码中坚持使用async/awaitPromise.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/awaitPromises,而且看起来也很整洁。由于Promises在某种程度上旨在替代callbacks,因此,如果您也将runInAction函数也转换为一个函数,那就很好了。

所以:

function runInAction(): Promise<void> {
  return new Promise(...);
}

.catch(() => runInAction('updating hotel with failure'));

作为副作用,这将防止链断裂,并使整个代码看起来更加一致。

重要:如果您在此类链的中间使用回调,则会中断执行代码的顺序。因此,请勿在promise中使用回调(除非其中包含resolve())。