【问题标题】:How can I use a javascript promise to make one function wait for another to finish running asynchronously?如何使用 javascript 承诺使一个函数等待另一个函数完成异步运行?
【发布时间】:2019-02-23 07:23:13
【问题描述】:
// 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% 的教程都使用),因为这会不必要地减慢应用程序的速度。我必须使用异步来满足分配要求。 请帮助我连接点以应用承诺和/或等待/然后在这种情况下适用。

【问题讨论】:

    标签: javascript asynchronous promise async-await


    【解决方案1】:

    您的 populateVenueIDs 函数无需等待调用 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);
    }
    

    【讨论】:

    • 这个答案是正确的,我只是在评论,因为我想强调你真的应该尝试使用 fetch,或者如果你不能使用 fetch,其他一些 ajax 库,因为 vanilla XMLHttpRequest 是工作真的很痛苦。如果您能够将库添加到项目中,Github 还为旧版浏览器提供了一个 fetch polyfill:github.com/github/fetch
    • @JensV 非常感谢。在尝试了上面的第一个解决方案之后,它仍然执行不正常,但这让我达到了 99% 的需要。我将在下面粘贴我的最终解决方案。我也将考虑切换到 fetch。
    • return Promise.all(promises) .then(function () { resolve('Done!'); populateFsPhotoRequestURLs(); }) }); populateVenueIDs;
    【解决方案2】:

    虽然我强烈认为@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 解决方案之前发布了这个:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-02
      • 2018-02-03
      • 2022-11-17
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多