Meteor - 运行 客户端异步回调 for 循环后的代码
Meteor - Run code after for-loop of async callbacks on the client
在 Meteor 中,我有一个充满异步地理编码请求的 for 循环发送到 google 地图 api。
完成所有地理编码后,我想显示一个 table,其中包含所有失败的地理编码尝试。
最好的模式是什么?据我了解,我有 3 个选项:
Promises - 我可以将 google 映射回调设置为一个 promise & 使用 thenable 到 return 错误布尔值,可能使用 bluebird polyfill。
NPM async - 我可以在每次迭代时调用 async.each
& 如果它是最后一次,return 错误布尔值是这样的:How to call a function after an asynchronous for loop of Object values finished executing
像这样使用会话变量:
Deps.autorun(function() {
console.log(Session.get('hasError'));
});
创建流星方法并使用 Meteor.wrapasync
???
调用它
任何有关 Meteor 最佳实践的指导都将非常有用,谢谢!
直到出现另一个答案(拜托!),我通过向循环函数添加回调处理程序解决了这个问题,当我调用该循环时,我传入了我的回调。
lookupAddress(function(hasError, errArr) {
if (hasError === false) {
console.log("no errors");
} else {
console.log (errArr);
}
});
这里是从实际功能中提取出来的好部分...
function lookupAddress(callback) {
var hasError = false;
var errArr = [];
var cursorClosed = false;
var outstandingCalls = 0;
for (i = 0; i < n; i++) {
(function (j) { //wrap in an iffe to get 'i' byVal, not byRef
if (j === n - 1) cursorClosed = true; //check if I'm on the last iteration
geocoder.geocode({'address': address}, function (results, status) {
if (status === "OK") {
doSomethingFancy();
} else {
hasError = true;
errArr.push(arr[j]);
}
outstandingCalls--; //reduce queue for each completed async call
if (cursorClosed && outstandingCalls === 0) { //if no more iters and we're on the last async call
return callback(hasError, errArr)
}
});
})(i);
outstandingCalls++; //for each loop iter add 1 to the async queue
}
}
我会这样做:
// Local collection, not synced to server
var geocodeErrors = new Mongo.Collection();
// Reactive variable to track completion
var geocodingComplete = new ReactiveVar(false);
var lookupThings = function (addresses) {
// How many are there?
var count = addresses.length;
// Count how many requests are complete
var complete = 0;
// Use underscore to make iteration easier
_.each(addresses, function (address) {
geocode(address, function (results, status) {
if (status === "OK") {
// do whatever
} else {
geocodeErrors.insert({
address: address,
otherData: "whatever"
});
}
complete++;
if (complete === count) {
geocodingComplete.set(true);
}
});
});
}
Template.results.helpers({
geocodeErrors: function () {
// Use an if statement to only display the errors when everything is done
if (geocodingComplete.get()) {
return geocodeErrors.find();
}
}
});
您可以使用此模板来显示列表:
<template name="results">
<ul>
{{#each geocodeErrors}}
<li>Address failed: {{address}}</li>
{{/each}}
</ul>
</template>
我认为主要的收获是 Meteor 风格是使用反应变量和集合而不是回调。
在 Meteor 中,我有一个充满异步地理编码请求的 for 循环发送到 google 地图 api。 完成所有地理编码后,我想显示一个 table,其中包含所有失败的地理编码尝试。 最好的模式是什么?据我了解,我有 3 个选项:
Promises - 我可以将 google 映射回调设置为一个 promise & 使用 thenable 到 return 错误布尔值,可能使用 bluebird polyfill。
NPM async - 我可以在每次迭代时调用
async.each
& 如果它是最后一次,return 错误布尔值是这样的:How to call a function after an asynchronous for loop of Object values finished executing像这样使用会话变量:
Deps.autorun(function() { console.log(Session.get('hasError')); });
创建流星方法并使用
Meteor.wrapasync
??? 调用它
任何有关 Meteor 最佳实践的指导都将非常有用,谢谢!
直到出现另一个答案(拜托!),我通过向循环函数添加回调处理程序解决了这个问题,当我调用该循环时,我传入了我的回调。
lookupAddress(function(hasError, errArr) {
if (hasError === false) {
console.log("no errors");
} else {
console.log (errArr);
}
});
这里是从实际功能中提取出来的好部分...
function lookupAddress(callback) {
var hasError = false;
var errArr = [];
var cursorClosed = false;
var outstandingCalls = 0;
for (i = 0; i < n; i++) {
(function (j) { //wrap in an iffe to get 'i' byVal, not byRef
if (j === n - 1) cursorClosed = true; //check if I'm on the last iteration
geocoder.geocode({'address': address}, function (results, status) {
if (status === "OK") {
doSomethingFancy();
} else {
hasError = true;
errArr.push(arr[j]);
}
outstandingCalls--; //reduce queue for each completed async call
if (cursorClosed && outstandingCalls === 0) { //if no more iters and we're on the last async call
return callback(hasError, errArr)
}
});
})(i);
outstandingCalls++; //for each loop iter add 1 to the async queue
}
}
我会这样做:
// Local collection, not synced to server
var geocodeErrors = new Mongo.Collection();
// Reactive variable to track completion
var geocodingComplete = new ReactiveVar(false);
var lookupThings = function (addresses) {
// How many are there?
var count = addresses.length;
// Count how many requests are complete
var complete = 0;
// Use underscore to make iteration easier
_.each(addresses, function (address) {
geocode(address, function (results, status) {
if (status === "OK") {
// do whatever
} else {
geocodeErrors.insert({
address: address,
otherData: "whatever"
});
}
complete++;
if (complete === count) {
geocodingComplete.set(true);
}
});
});
}
Template.results.helpers({
geocodeErrors: function () {
// Use an if statement to only display the errors when everything is done
if (geocodingComplete.get()) {
return geocodeErrors.find();
}
}
});
您可以使用此模板来显示列表:
<template name="results">
<ul>
{{#each geocodeErrors}}
<li>Address failed: {{address}}</li>
{{/each}}
</ul>
</template>
我认为主要的收获是 Meteor 风格是使用反应变量和集合而不是回调。