如何相互依赖执行多个异步功能?

时间:2018-09-10 19:25:17

标签: javascript async-await geocoding ecmascript-2017

似乎我了解async / await的行为,但现在到现在,我深陷于自己的问题,无法解决它。 我正在尝试创建天气应用,因此我需要先请求纬度和经度,然后获取该信息以将请求发送到天气API并获取天气预报。正如Google文档

所述
  

由于Google Maps API需要调用外部服务器,因此访问地理编码服务是异步的。

所以我正在尝试使用async / await来处理它。

import Search from './models/Search';
import * as searchView from './views/searchView';
import { elements } from './views/base';

/*
* Search controller
*/

const state = {

};

const controlSearch = async () => {
  const query = searchView.getInput();

  if (query) {
    state.forecast = new Search(query);

    try {
      await state.forecast.codeAddress();
      await state.forecast.getForecast(state.forecast);
      console.log(state);
    } catch (error) {
      console.log(error);
    }
  }
};

elements.searchForm.addEventListener('submit', (e) => {
  e.preventDefault();
  controlSearch();
});

这是我的控制人。在底部,我将eventListener设置为form,用户将使用它来搜索城市,然后获取城市的天气预报。

这是我的搜索模型

import { key, proxy } from '../config';

export default class Search {
  constructor(query) {
    this.query = query;
  }

  codeAddress() {
    const geocoder = new google.maps.Geocoder();
    geocoder.geocode({ address: this.query }, (results, status) => {
      if (status === 'OK') {
        this.latitude = results[0].geometry.location.lat();
        this.longitude = results[0].geometry.location.lng();
        console.log(this.latitude, this.longitude, 'lat long');
      }
    });
  }

  async getForecast(geometry) {
    console.log(geometry, 'geometry');
    const result = await fetch(`${proxy}https://api.darksky.net/forecast/${key}/${geometry.latitude},${geometry.longitude}`);
    const forecast = await result.json();
    forecast.then((res) => {
      this.forecast = res;
    });
  }
} 

问题是,当请求darkSky API时,geometry.latitude和几何经度未定义。

  

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

codeAddress不会await进行任何操作,也不返回要await处理的内容。即使geocode尚未完成,它也会立即关闭。让它返回可以Promise编辑的await

codeAddress() {
  return new Promise((resolve, reject) => {
    const geocoder = new google.maps.Geocoder();
    geocoder.geocode({
      address: this.query
    }, (results, status) => {
      if (status === 'OK') {
        this.latitude = results[0].geometry.location.lat();
        this.longitude = results[0].geometry.location.lng();
        console.log(this.latitude, this.longitude, 'lat long');
        resolve();
      } else {
        reject();
      }
    });
  });
}


不幸的是,您将需要手动返回Promise,因为Geocoder.geocode() API仅遵循异步的回调样式,并且await仅等待.then()-ables(例如Promise)。

答案 1 :(得分:0)

codeAddress是异步的(因为响应是在回调中处理的),但是您并未将其视为异步。试试这个:

async codeAddress() {
  const geocoder = new google.maps.Geocoder();
  return new Promise((resolve, reject) => {
    geocoder.geocode({ address: this.query }, (results, status) => {
      if (status === 'OK') {
        this.latitude = results[0].geometry.location.lat();
        this.longitude = results[0].geometry.location.lng();
        console.log(this.latitude, this.longitude, 'lat long');
        resolve();
      } else {
        reject();
      }
    });
  });
}

当然还有其他方法可以将带有回调的函数转换为异步。