从 Meteor.method 内的多个承诺返回值
Returning value from multiple promises within Meteor.method
在研究了 Futures、Promises、wrapAsync 之后,我仍然不知道如何解决这个问题
我有这个方法,它获取一组图像,将其发送到 Google Cloud Vision 进行徽标检测,然后将所有检测到的带有徽标的图像推送到一个数组中,我尝试在其中 return 在我的方法中。
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);
});
空数组总是 returned,并且可以理解,因为方法 returned logosArray
在 Google 完成所有处理之前 return 结果。
遇到这种情况怎么处理?
- 使用 Meteor 方法,您实际上可以简单地 "return a Promise",服务器方法将在内部等待 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
}
});
- 您还可以将 Promise 语法转换为
async
/ await
。通过这样做,您不再显式 return Promise(但在幕后仍然如此),但 "wait" 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);
}
}
});
- 一旦理解了这个概念,就可以开始处理多个异步操作,并在所有操作完成后 return 结果。为此,您可以简单地使用
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);
}, []);
}
});
在研究了 Futures、Promises、wrapAsync 之后,我仍然不知道如何解决这个问题
我有这个方法,它获取一组图像,将其发送到 Google Cloud Vision 进行徽标检测,然后将所有检测到的带有徽标的图像推送到一个数组中,我尝试在其中 return 在我的方法中。
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);
});
空数组总是 returned,并且可以理解,因为方法 returned logosArray
在 Google 完成所有处理之前 return 结果。
遇到这种情况怎么处理?
- 使用 Meteor 方法,您实际上可以简单地 "return a Promise",服务器方法将在内部等待 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
}
});
- 您还可以将 Promise 语法转换为
async
/await
。通过这样做,您不再显式 return Promise(但在幕后仍然如此),但 "wait" 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);
}
}
});
- 一旦理解了这个概念,就可以开始处理多个异步操作,并在所有操作完成后 return 结果。为此,您可以简单地使用
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);
}, []);
}
});