繁体   English   中英

从Meteor.method中的多个承诺中返回值

[英]Returning value from multiple promises within Meteor.method

在看了一堆期货,Promises,wrapAsync后,我仍然不知道如何解决这个问题

我有这种方法,它采用一系列图像,将其发送到Google Cloud Vision进行徽标检测,然后将所有检测到的图像与徽标一起推送到数组中,我尝试在我的方法中返回。

Meteor.methods({
  getLogos(images){
    var logosArray = [];
    images.forEach((image, index) => {
        client
        .logoDetection(image)
        .then(results => {
            const logos = results[0].logoAnnotations;
            if(logos != ''){
                logos.forEach(logo => logosArray.push(logo.description));
            }
        })
    });
    return logosArray;      
  },
});

但是,从客户端调用该方法时:

Meteor.call('getLogos', images, function(error, response) {
  console.log(response);
});

总是返回空数组,这是可以理解的,因为该方法在Google完成处理所有这些并返回结果之前返回了logosArray

如何处理这种情况?

  1. 使用Meteor方法,您实际上可以简单地“返回Promise”,并且Server方法将在内部等待Promise解析,然后将结果发送到客户端:
Meteor.methods({
  getLogos(images) {
    return client
      .logoDetection(images[0]) // Example with only 1 external async call
      .then(results => {
        const logos = results[0].logoAnnotations;
        if (logos != '') {
          return logos.map(logo => logo.description);
        }
      }); // `then` returns a Promise that resolves with the return value
          // of its success callback
  }
});
  1. 您还可以将Promise语法转换为async / await 通过这样做,你不再明确地返回一个Promise(但在底层仍然如此),但“等待”Promise在你的方法代码中解决。
Meteor.methods({
  async getLogos(images) {
    const results = await client.logoDetection(images[0]);
    const logos = results[0].logoAnnotations;
    if (logos != '') {
      return logos.map(logo => logo.description);
    }
  }
});
  1. 一旦理解了这个概念,就可以逐步处理几个异步操作,并在完成所有操作后返回结果。 为此,您可以简单地使用Promise.all
Meteor.methods({
  getLogos(images) {
    var promises = [];
    images.forEach(image => {
      // Accumulate the Promises in an array.
      promises.push(client.logoDetection(image).then(results => {
        const logos = results[0].logoAnnotations;
        return (logos != '') ? logos.map(logo => logo.description) : [];
      }));
    });
    return Promise.all(promises)
      // If you want to merge all the resulting arrays...
      .then(resultPerImage => resultPerImage.reduce((accumulator, imageLogosDescriptions) => {
        return accumulator.concat(imageLogosDescriptions);
      }, [])); // Initial accumulator value.
  }
});

或者使用async / await

Meteor.methods({
  async getLogos(images) {
    var promises = [];
    images.forEach(image => {
      // DO NOT await here for each individual Promise, or you will chain
      // your execution instead of executing them in parallel
      promises.push(client.logoDetection(image).then(results => {
        const logos = results[0].logoAnnotations;
        return (logos != '') ? logos.map(logo => logo.description) : [];
      }));
    });
    // Now we can await for the Promise.all.
    const resultPerImage = await Promise.all(promises);
    return resultPerImage.reduce((accumulator, imageLogosDescriptions) => {
      return accumulator.concat(imageLogosDescriptions);
    }, []);
  }
});

暂无
暂无

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

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