【问题标题】:Angular Async Form Validator - How to Await response from getDistanceMatrix call backAngular Async Form Validator - 如何等待 getDistanceMatrix 回调的响应
【发布时间】:2020-01-03 09:11:02
【问题描述】:

我有一个带有自定义异步验证器的 deliveryAddress 字段的反应式表单。我使用谷歌地方 API 来检查距离。

但是,API 需要回调来获取响应。这会导致我的异步验证器出现问题,因为我不知道如何从调用返回到外部函数中获取响应。

我在回调中使用响应来解析距离。根据距离,该字段有效或无效。

Google Maps API here 的文档。

this.orderObject = this.fb.group({
  deliveryAddress: ['', [Validators.required], this.validDeliveryAddress.bind(this)]
});

async validDeliveryAddress(control: AbstractControl) {

  const origin2 = this.restaurantAddress;
  const service = new google.maps.DistanceMatrixService();

  let resp = await service.getDistanceMatrix({
    origins: [origin2],
    destinations: [control.value],
    travelMode: google.maps.TravelMode.DRIVING,
    unitSystem: google.maps.UnitSystem.IMPERIAL,
    // HERE HOW TO GET response IN OUTER LAYER AFTER DONE EXECUTING?
  }, async(response, status) => {
    resp = await this.handleMapResponse(response, status);
    console.log('resp', resp);
    return resp;
  });

  console.log('resp', resp);

  // end outer function
}


// CALL BACK FUNCTION HERE
async handleMapResponse(response, status): Promise < any > {

  let from;
  let to;
  let duration;
  let distance: string;

  // if true, means not a valid address sent yet
  if (response.destinationAddresses.includes('')) {
    console.log('not valid addresss yet')
    return {
      validAddress: true
    };
  }

  if (status == google.maps.DistanceMatrixStatus.OK) {
    console.log('status ok');
    let origins = response.originAddresses;
    let destinations = response.destinationAddresses;
    console.log('origins', origins);
    console.log('destinations', destinations);
    for (let i = 0; i < origins.length; i++) {
      let results = response.rows[i].elements;
      for (let j = 0; j < results.length; j++) {
        let element = results[j];
        distance = element.distance.text;
        duration = element.duration.text;
        from = origins[i];
        to = destinations[j];
      }
    }
  } else {
    console.log('not ok', status);
  }
  console.log('from', from);
  console.log('to', to);
  console.log('distance', distance);
  console.log('duration', duration);

  if (distance.includes("ft")) {
    return {
      'validAddress': true
    }
  } else if (parseFloat(distance) <= 3) {
    return {
      'validAddress': true
    }
  } else {
    return {
      'validAddress': true
    }
  }
}

【问题讨论】:

  • 不太清楚你为什么要创建handleMapResponse async。无论如何,它都会被同步调用。另外,它的任务是确定您是否需要显示错误。您能否分享您对service.getDistanceMatrix 的实现

标签: javascript angular typescript google-maps


【解决方案1】:

您可以将响应转换为 Promise 并等待。

async validDeliveryAddress(control: AbstractControl) {
  const origin2 = this.restaurantAddress;
  const service = new google.maps.DistanceMatrixService();

  const {response, status} = await new Promise(resolve => 
    service.getDistanceMatrix({
      origins: [origin2],
      destinations: [control.value],
      travelMode: google.maps.TravelMode.DRIVING,
      unitSystem: google.maps.UnitSystem.IMPERIAL,
    }, (response, status) => resolve({response, status}))
  );

  const resp = await this.handleMapResponse(response, status);
}

【讨论】:

  • 您好,谢谢,成功了!虽然,我不太了解语法。你能帮我理解吗? 1) 为什么我们需要 const { response, status } = ... ?它只是一个占位符吗?我们可以只用 await new Promise(resolve => ... 2) 来做到这一点吗? const resp = await this.handleMapResponse(response, status);谢谢!
  • 当然,在调用resolve 时,我传入了一个对象{response, status},它是{response: response, status: status} 的简写。那是等待的返回值。通常,您会写:const returnedObj = await new Promise....; const response = returnedObj.response; const status = returnedObj.status。解构语法 const {response, status} = await new Promise... 正是这样做的。
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 2019-08-14
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多