我很难过
基本上,我有一个http REST API,我可以向其发出异步请求并提供回调。我还有一个Web前端,可以在任意位置异步调用此api。
问题是api需要'nonce'。每个后续请求的数字大于最后一个。以这种方式产生这个数字很容易。确保请求以正确的顺序到达..不是那么多。
我需要一种方法来支持我的api模块,我可以进行函数调用并提供回调。并且模块将处理随后的任何先前调用将在它发出新请求之前完成。
当然async模块允许同步运行异步函数,但它需要我知道我之前要触发的所有操作。使用我当前的系统,可能会在处理第一个请求时添加新请求。
一般来说api调用是这样的
// the api module
var nextNonceFunc = function() {
var d = new Date();
var seconds = Math.floor(d.getTime() / 1000);
var nonce = seconds;
return function() {
return nonce++;
}
}();
var privateAPI = function(key, secret) {
var self = this;
var api = new API(key, secret, nextNonceFunc);
//information about the user
self.getInfo = function (callback) {
api.getInfo(callback);
};
}
// ... bla bla set up routes ect. -> enter the server request callback
// server module
// we make an api instance
var api = new privateAPI(key, secreet);
// some time later we make an api call
api.getInfo(function(err, data){
if (err) {
//handle error
}
// dosomthing with the data
})
我正在寻找让privateAPI
对象排队获取请求的方法。
答案 0 :(得分:1)
在凯文指出存在async.queue后,我能够构建以下包装器
var async = require('async');
//actes as a wrapper for the passed api
module.exports = function(obj) {
var self = this;
var q = async.queue(function (task, callback) {
var args = task.args;
args.push(function(err, data){
task.cb(err, data);
if (err) return callback(err);
callback();
})
obj[task.func].apply(obj, args);
}, 1);
var keys = Object.keys(obj);
var buildFuncWrapper = function(i) {
self[keys[i]] = function() {
var args = Array.prototype.slice.call(arguments);
var task = {
func: keys[i],
args: args.slice(0, args.length - 1),
cb: args.slice(args.length - 1, args.length)[0]
};
q.push(task, function(){
if (global.DEBUG) console.log("[SYNC WRAPPER] finished wrapped call to: ", keys[i]);
})
}
}
var buildPropWrapper = function(i) {
Object.defineProperty(self, keys[i], {
get: function () { return obj[keys[i]]},
writable : false,
enumerable: true
})
}
for (var i = 0; i < keys.length; i++) {
if (typeof(obj[keys[i]]) === "function" ) {
buildFuncWrapper(i);
} else {
buildPropWrapper(i);
}
}
}
基本上我可以将现有的API对象传递给它,它会通过队列转发对它的函数所做的所有调用,因为队列的并发性为1,一次只能处理一个调用。
之后,这是一个相当简单的事情,确保只存在这个包装的api对象的一个版本。
答案 1 :(得分:0)
某种客户端队列可以在这里工作。请注意,这是非常快速,肮脏和未经测试的,并且为了方便我假设jquery:
var ajaxQueue = function() {
var _queue = [];
var _isRunning = false;
function isRunning() {
return _isRunning;
}
function run(ajaxOptions) {
_isRunning = true;
$.ajax({
url : ajaxOptions.url,
method : ajaxOptions.method,
//etc
success : function() {
_isRunning = false;
if (ajaxOptions.callback) {
ajaxOptions.callback();
}
if (queue.length) {
var next = queue.shift();
run(next);
}
}
});
}
return {
add : function(ajaxOptions){
if (isRunning()) {
_queue.push(ajaxOptions);
// return the index of the current queue item
return _queue.length;
} else {
run(ajaxOptions);
}
},
remove : function(queueIndex) {
delete _queue[queueIndex];
}
}
}