繁体   English   中英

如何使用 javascript 承诺使一个函数等待另一个函数异步完成运行?

[英]How can I use a javascript promise to make one function wait for another to finish running asynchronously?

// TODO: FIX CODE - IT IS STILL NOT WAITING FOR populateVenueIDs
// BEFORE CALLING populateFsPhotoRequestURLs
// must use async, not sync to meet assignment requirements.

let populateVenueIDs = new Promise(function(resolve, reject) {
  for (let y = 0; y < window.coffeeShopLocations().length; y++) {
    let getVenueIDFromFS = new XMLHttpRequest();
    getVenueIDFromFS.open('GET', window.fsURL[y]);
    getVenueIDFromFS.onload = function() {
      let responseFromFS = JSON.parse(getVenueIDFromFS.responseText);
      window.fsVenueID[y] = responseFromFS.response.venues[0].id;
      console.log(window.fsVenueID[y]);
    }; 
    getVenueIDFromFS.send();
  } 
  resolve("done!");
}); 

function populateFsPhotoRequestURLs() {
  for (let y = 0; y < window.coffeeShopLocations().length; y++) {
    window.fsPhotoEndpoint[y] = 'https://api.foursquare.com/v2/venues/'
      + window.fsVenueID[y] + '/photos';
    window.fsPhotoRequestURL[y] = fsPhotoEndpoint + '?' + fsPhotoParams;
    console.log(window.fsPhotoRequestURL[y]);
  } 
} 


populateVenueIDs.then(
  populateFsPhotoRequestURLs()
);

在运行 populateFsPotoRequestURLs 之前,它仍然不会等待 populateVenueIDs。

我还尝试了 await、promise 和 then 的变体。 我已经阅读了大约 15 个关于这些主题的教程,但没有一个足够接近我想要的。 我不想使用超时(90% 的教程都使用),因为这会不必要地减慢应用程序的速度。 我必须使用 async 来满足分配要求。 请帮助我将这些点联系起来以应用在这种情况下适用的承诺和/或等待/然后。

您的populateVenueIDs函数只是解析为 done 而不等待onload函数。 如果可以, fetch将是一个不错的选择,因为它返回承诺,但 IE 不支持。

您可以做的是为循环的每次迭代创建一个承诺,并使用Promise.all(arrayOfPromises)等待所有请求。 这甚至会并行执行所有XMLHttpRequest

示例代码:

let populateVenueIDs = new Promise(function(resolve, reject) {
    let promises = [];

    for (let y = 0; y < window.coffeeShopLocations().length; y++) {
        promises.push(new Promise(function (resolve) {
            let getVenueIDFromFS = new XMLHttpRequest();
            getVenueIDFromFS.open('GET', window.fsURL[y]);
            getVenueIDFromFS.onload = function() {
                let responseFromFS = JSON.parse(getVenueIDFromFS.responseText);
                window.fsVenueID[y] = responseFromFS.response.venues[0].id;
                console.log(window.fsVenueID[y]);
                resolve();
            };
            getVenueIDFromFS.send();
        }));

    }
    return Promise.all(promises)
        .then(function () {
            resolve('Done!');
        })
}); 

获取解决方案

正如您所说,这是一项任务,您可能可以将 ES6 与asyncawait一起使用,因此这将是一个不错的解决方案:

async function populateVenueIDs() {

    let promises = [];

    for (let y = 0; y < window.coffeeShopLocations().length; y++) {
        promises.push(new Promise(async resolve => {
            const response = await fetch(window.fsURL[y]);
            const data = await response.json();
            window.fsVenueID[y] = data.venues[0].id;
            resolve();
        }));
    }

    await Promise.all(promises);
}

虽然我强烈认为@JensV 有正确的答案,并且我在评论中这么说,但我只是想跟进一下,如果您使用 fetch,您的代码可能会是什么样子(我只包含了 JensV 的答案的相关部分。

var promises = [];

for (let y = 0; y < window.coffeeShopLocations().length; y++) {
    promises.push(fetch(window.fsURL[y])
      .then(response => response.json())
      .then(data => {
        window.fsVenueID[y] = data.response.venues[0].id;
      }));
}

编辑:为了后人的缘故,我在 Jens 添加他的 fetch 解决方案之前发布了这个:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM