Javascript 如何在Node.js模块中处理异步回调?
这是我第一次尝试组合一个节点模块,但我仍在努力研究如何构造异步回调。这就是一个恰当的例子。现在我正在尝试使用Javascript 如何在Node.js模块中处理异步回调?,javascript,node.js,callback,promise,Javascript,Node.js,Callback,Promise,这是我第一次尝试组合一个节点模块,但我仍在努力研究如何构造异步回调。这就是一个恰当的例子。现在我正在尝试使用featureService.getCount(),但没有得到任何响应。使用断点,我知道featureService.getUniqueIds()正在工作 因为回调在那里,所以我假设我没有返回长度的原因是getCount中的回调还没有响应。在看了下午的大部分时间后,除了递归循环检查要用超时填充的值之外,我并没有真正想出一个很好的解决方案,我想知道如何更好地构造代码以完成手头的任务 我读过一
featureService.getCount()
,但没有得到任何响应。使用断点,我知道featureService.getUniqueIds()
正在工作
因为回调在那里,所以我假设我没有返回长度的原因是getCount中的回调还没有响应。在看了下午的大部分时间后,除了递归循环检查要用超时填充的值之外,我并没有真正想出一个很好的解决方案,我想知道如何更好地构造代码以完成手头的任务
我读过一些关于承诺的书。这是一个适用的实例还是一个可行的解决方案?我真的不知道如何实现承诺,但在这种情况下,这是合乎逻辑的
显然我在这里迷路了。谢谢你能提供的任何帮助
var Client = require('node-rest-client').Client;
var client = new Client();
var featureService = function(endpoint){
var uniqueIds;
var count;
// get list of unique id's
this.getUniqueIds = function(){
if (!uniqueIds) {
var options = {
parameters: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnIdsOnly: 'true'
}
};
client.get(endpoint + '/query', options, function(data, res){
var dataObject = JSON.parse(data);
var uniqueIds = dataObject.objectIds;
return uniqueIds;
});
} else {
return uniqueIds;
}
};
// get feature count
this.getCount = function(){
// get uniqueIds
uniqueIds = this.getUniqueIds();
// get length of uniqueIds
count = uniqueIds.length;
};
// get list of unique attribute values in a single field for typeahead
this.getTypeaheadJson = function(field){};
// find features in a field with a specific value
this.find = function(field, value){};
};
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
var afs = new featureService(endpoint);
console.log(afs.getCount());
exports.featureService = featureService;
现在,在使用request
和bluebird
文档(我无法使上述模块正常工作)之后,我完成了这项工作,但无法计算出如何获得要使用的计算值,即迭代次数
var Promise = require("bluebird"),
request = Promise.promisifyAll(require("request"));
var FeatureService = function(){
// get count from rest endpoint
var getCount = function(){
var optionsCount = {
url: endpoint + '/query',
qs: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnCountOnly: 'true'
}
};
return request.getAsync(optionsCount)
.get(1)
.then(JSON.parse)
.get('count');
};
// get max record count for each call to rest endpoint
var getMaxRecordCount = function(){
var optionsCount = {
url: endpoint,
qs: {
f: 'json'
}
};
return request.getAsync(optionsCount)
.get(1)
.then(JSON.parse)
.get('maxRecordCount');
};
// divide the total record count by the number of records returned per query to get the number of query iterations
this.getQueryIterations = function(){
getCount().then(function(count){
getMaxRecordCount().then(function(maxCount){
return Math.ceil(count/maxCount);
});
});
};
};
// url to test against
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
// create new feature service object instance
afs = new FeatureService();
// This seems like it should work, but only returns undefined
console.log(afs.getQueryIterations());
// this throws an error telling me "TypeError: Cannot call method 'then' of undefined"
//afs.getQueryIterations().then(function(iterCount){
// console.log(iterCount);
//});
是的,使用承诺!他们是一个,正是为了这个目的而制造的,而且有一个,他们很容易使用。就你而言:
var Promise = require('bluebird'); // for example, the Bluebird libary
var Client = Promise.promisifyAll(require('node-rest-client').Client);
var client = new Client();
function FeatureService(endpoint) {
var uniqueIds;
var count;
// get list of unique id's
this.getUniqueIds = function(){
if (!uniqueIds) { // by caching the promise itself, you won't do multiple requests
// even if the method is called again before the first returns
uniqueIds = client.getAsync(endpoint + '/query', {
parameters: {
f: 'json',
where: "OBJECTID LIKE '%'",
returnIdsOnly: 'true'
}
})
.then(JSON.parse)
.get("objectIds");
}
return uniqueIds;
};
// get feature count
this.getCount = function(){
if (!count)
count = this.getUniqueIds() // returns a promise now!
.get("length");
return count; // return a promise for the length
};
// get list of unique attribute values in a single field for typeahead
this.getTypeaheadJson = function(field){};
// find features in a field with a specific value
this.find = function(field, value){};
};
var endpoint = 'http://services.arcgis.com/SgB3dZDkkUxpEHxu/arcgis/rest/services/aw_accesses_20140712b/FeatureServer/1';
var afs = new FeatureService(endpoint);
afs.getCount().then(function(count) {
console.log(count);
}); // you will need to use a callback to do something with async results (always!)
exports.FeatureService = FeatureService;
在这里,使用,您只需使用.getAsync()
而不是.get()
,就可以得到结果的承诺
这是正确的想法!只有您始终希望
从返回内容,然后处理程序,这样.then()
调用返回的承诺将使用该值解析
// divide the total record count by the number of records returned per query to get the number of query iterations
this.getQueryIterations = function(){
return getCount().then(function(count){
// ^^^^^^ return the promise from the `getQueryIterations` method
return getMaxRecordCount().then(function(maxCount){
// ^^^^^^ return the promise for the iteration number
return Math.ceil(count/maxCount);
});
});
};
现在,你得到了一个,这将立即生效:
afs.getQueryIterations().then(function(iterCount){
console.log(iterCount);
});
我昨天晚上花了大部分时间,今天早上花了几个小时,试图让它为我的目的发挥作用。我一直在琢磨如何最终摆脱异步循环。我需要能够调用FeatureService.getCount()
并返回计数。谢天谢地,我正在使用Git。我尝试过很多不同的分支,都数不清了。关于如何修改它以获得我想要的东西,有什么想法吗?没有,从getCount
返回一个数字是绝对不可能的。使用异步函数的函数本身需要异步,并提供回调参数或返回承诺。返回一个承诺的数字(就像我的答案一样)是你能得到的最好的。看看是否需要在循环中使用getCount()
。我深入到Bluebird文档中,使用require
完全删除了我的代码,以模仿Bluebird的示例,并包括上面更新的代码。关于承诺的想法,我开始慢慢地绞尽脑汁,但现在我无法弄清楚如何从函数中获得查询迭代,无论是直接还是通过承诺。有什么想法吗?现在我还试图围绕中详述的函数创建新的承诺,但这也不起作用@Bergi,非常感谢您的帮助……或者他们更改了他们的API,因为这是上次编写并确认有效的答案。您的使用也很好,尽管通常承诺类本身就足够了。另见
afs.getQueryIterations().then(function(iterCount){
console.log(iterCount);
});