简体   繁体   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()
);

It is still not waiting for populateVenueIDs before running populateFsPotoRequestURLs.在运行 populateFsPotoRequestURLs 之前,它仍然不会等待 populateVenueIDs。

I have also tried variants of await, promise, and then.我还尝试了 await、promise 和 then 的变体。 I have read about 15 tutorials about those topics, but none are close enough to do what I want.我已经阅读了大约 15 个关于这些主题的教程,但没有一个足够接近我想要的。 I don't want to use a timeout (which 90% of tutorials use) because that would unnecessarily slow down the application.我不想使用超时(90% 的教程都使用),因为这会不必要地减慢应用程序的速度。 I have to use async to meet the assignment requirements.我必须使用 async 来满足分配要求。 Please help me connect the dots to apply a promise and/or await/then that will apply in this situation.请帮助我将这些点联系起来以应用在这种情况下适用的承诺和/或等待/然后。

Your populateVenueIDs function just resolves to done without waiting for the onload functions to be called.您的populateVenueIDs函数只是解析为 done 而不等待onload函数。 If you can, fetch would be a nice alternative because it returns promises but that isn't supported in IE.如果可以, fetch将是一个不错的选择,因为它返回承诺,但 IE 不支持。

What you can do, is create a promise for each iteration of your loop and use Promise.all(arrayOfPromises) to wait for all requests.您可以做的是为循环的每次迭代创建一个承诺,并使用Promise.all(arrayOfPromises)等待所有请求。 This will even execute all XMLHttpRequest in parallel!这甚至会并行执行所有XMLHttpRequest

Example code:示例代码:

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!');
        })
}); 

Fetch Solution获取解决方案

As you've said this is an assignment, you probably can use ES6 with async and await so this would be a fancy solution:正如您所说,这是一项任务,您可能可以将 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);
}

While I feel strongly that @JensV had the right answer, and I said so in my comment, I just wanted to follow up on what your code might look like if you used fetch (I only included the relevant piece of JensV's answer.虽然我强烈认为@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;
      }));
}

EDIT: For posterity's sake I posted this before Jens added his fetch solution :)编辑:为了后人的缘故,我在 Jens 添加他的 fetch 解决方案之前发布了这个:)

暂无
暂无

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

相关问题 在执行另一个函数之前,如何使jquery等待一个函数完成? - How can I make jquery wait for one function to finish before executing another function? 骨干Javascript:等待某个函数完成,然后再运行另一个 - Backbone Javascript: Wait for a function to finish before running another one 如何等待 function 完成后再运行另一个或 rest 的代码? - How to wait for function to finish before running another one or rest of the code? 我怎样才能让这段代码等待第一个 function 完成,然后再执行第二个或 function,秒数更少? - How can I make this code wait for the first function to finish before executing the second one or the function with less seconds? 如何在不使用任何外部API的情况下使javascript函数等待其他函数完成? - How can I make javascript function to wait for other function to finish without using any external APIs? 如何让一个方法等待另一个方法完成? - How can I make a method wait for another method to finish? 在返回 function 的变量之前,如何等待 promise 完成? - How do I wait for a promise to finish before returning the variable of a function? 如何使一个函数使用链接等待另一个函数在javascript中完成处理? - How to have one function wait for another function to finish processing in javascript using chaining? 如何让Grunt在运行另一个任务之前等待任务完成? - How to make Grunt wait for a task to finish before running another? 如何使JavaScript承诺等待for()循环内的另一个承诺被解决 - How to make JavaScript promise wait for another promise to be resolved inside for() loop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM