【问题标题】:How to wait for fetch to complete before running another function如何在运行另一个函数之前等待 fetch 完成
【发布时间】:2020-07-02 00:11:28
【问题描述】:

我目前正在尝试创建一个带有标记的地图,如果用户之前曾指出该标记是他们的“最爱”之一,我希望某些标记由不同的图标表示。

为此,我尝试使用一个函数,该函数首先获取数据,然后将部分数据推送到一个数组中,然后我使用另一个函数创建一个地图并用标记填充它。我希望第二个函数仅在第一个函数完成后运行。不幸的是,每次我运行代码时,所有标记都是相同的,并且似乎应该包含所有收藏站点的 ID 的数组是空的。我认为这意味着等待无法正常工作,因为第一个函数尚未完成运行。

代码是:

var favouriteStops = []

async function firstFunction(){
    fetch("api/favstop/")
    .then(response => {
        return response.json();
    })
    .then(data => {
    for(var i = 0; i<= data.length; i++){
        favouriteStops.push(data[i].stopid)
     }
 })
};


function addFavStop (){
        console.log(favouriteStops)
    }

async function initMap(){

    await firstFunction();
    //Map options
    var options = {
        zoom: 15,
        center: {lat:53.3477, lng:-6.2800},
        styles: mapStyle,
        disableDefaultUI: true
    }

    //Creating the map 
    var map = new google.maps.Map(document.getElementById('map'), options);


    //Add marker function
    function addMarker(stop){

        var coords = {lat: stop.lat, lng: stop.long}
        //Style for the icon
        if (favouriteStops.includes(stop.id)){
            var icon = {
                url: '../static/images/favourite.png',
                scaledSize: new google.maps.Size(12, 12)
            };
        } else {
            var icon = {
                url: '../static/images/bus-stop.png',
                scaledSize: new google.maps.Size(12, 12)
            };
            console.log(favouriteStops, stop.id)
        }

        var marker = new google.maps.Marker({
            position: coords,
            map:map,
            icon: icon,
            scaledSize: new google.maps.Size(1, 1),
            name:stop.name,
            id:stop.id
        })

        var infoWindow = new google.maps.InfoWindow({
            content: marker.name + '<br>' + '<button htmlType="submit" onClick=addFavStop()> Add Stop As Favourite </button>'
        });

        marker.addListener('click', function(){
            infoWindow.open(map, marker);
        });

    }

    //Adding markers for each stop
    for(var i = 0;i < stops_import.length;i++){
        addMarker(stops_import[i]);
    }
}

【问题讨论】:

  • async 函数需要return一个promise,所以只需在firstFunction中的fetch之前添加return

标签: javascript async-await fetch


【解决方案1】:

要让await 真正等到fetch 完成,您应该返回承诺:

async function firstFunction(){
  return fetch("api/favstop/")
  .then(response => {
    return response.json();
  })
  .then(data => {
    for(var i = 0; i<= data.length; i++){
      favouriteStops.push(data[i].stopid)
    }
  })
};

【讨论】:

  • 当我将 firstFunction 更改为此时,地图无法加载。在控制台中,我收到一条错误消息:“Uncaught (in promise) TypeError: Cannot read property 'stopid' of undefined”
  • 这是一个不同的问题。可能是因为您在数组中只有 stopid 而不是整个 stop 项目,但是您发布的代码并没有告诉我们 stops_import 实际上是什么。
【解决方案2】:

您可以通过在firstFunction 中使用await 轻松解决此问题,例如:

async function firstFunction() {
  const response = await fetch("api/favstop/")
  const data = await response.json();
  for (var i = 0; i <= data.length; i++) {
    favouriteStops.push(data[i].stopid)
  }
};

或者,像这样返回承诺:

async function firstFunction() {
  return fetch("api/favstop/")
    .then(response => {
      return response.json();
    })
    .then(data => {
      for (var i = 0; i <= data.length; i++) {
        favouriteStops.push(data[i].stopid)
      }
    })
};

【讨论】:

  • 不幸的是,这些都不适合我。在这两种情况下,地图都无法加载。在控制台中,我收到一条错误消息:“Uncaught (in promise) TypeError: Cannot read property 'stopid' of undefined”。
【解决方案3】:

您不需要在异步函数中使用承诺链。事实上,它有点违背了整个目的。所以,你的异步函数看起来有点像这样:

async function firstFunction(){
   const fetcher = await fetch("api/favstop/");
   const data = await fetcher.json();
   
   for(var i = 0; i<= data.length; i++){
      favouriteStops.push(data[i].stopid)
   }
};

【讨论】:

  • 当我将第一个函数更改为此时,我收到以下错误:“无法读取未定义的属性 'stopid'”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多