Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 同步异步进行的异步调用_Javascript_Node.js_Rest_Asynchronous_Synchronization - Fatal编程技术网

Javascript 同步异步进行的异步调用

Javascript 同步异步进行的异步调用,javascript,node.js,rest,asynchronous,synchronization,Javascript,Node.js,Rest,Asynchronous,Synchronization,我被难住了 基本上,我有一个HTTPRESTAPI,我可以向它发出异步请求并提供回调。我还有一个web前端,可以在任意时间、任意位置异步调用此api 问题是api需要一个“nonce”。每个后续请求中大于最后一个的数字。以这种方式生成这个数字很容易。确保请求以正确的顺序到达。。没有那么多 我需要一种方法,在我的api模块之外,我可以进行函数调用并提供回调。该模块将进行处理,以确保在发出新请求之前,任何先前发出的呼叫都将完成 当然,有一个模块允许同步运行异步函数,但它要求我知道我之前要启动的所有操

我被难住了

基本上,我有一个HTTPRESTAPI,我可以向它发出异步请求并提供回调。我还有一个web前端,可以在任意时间、任意位置异步调用此api

问题是api需要一个“nonce”。每个后续请求中大于最后一个的数字。以这种方式生成这个数字很容易。确保请求以正确的顺序到达。。没有那么多

我需要一种方法,在我的api模块之外,我可以进行函数调用并提供回调。该模块将进行处理,以确保在发出新请求之前,任何先前发出的呼叫都将完成

当然,有一个模块允许同步运行异步函数,但它要求我知道我之前要启动的所有操作。在我的当前系统中,当处理第一个请求时,可能会添加新的请求。 通常,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
对象对它收到的请求进行排队。

某种客户端队列可以在这里工作。注意,这是非常快速、肮脏且未经测试的,为了方便起见,假设使用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];
         }
    }
}

在Kevin指出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);
        }
    }
}
var async=require('async');
//actes作为传递的api的包装器
module.exports=功能(obj){
var self=这个;
var q=async.queue(函数(任务、回调){
var args=task.args;
参数推送(函数(错误、数据){
任务.cb(错误,数据);
if(err)返回回调(err);
回调();
})
obj[task.func].apply(obj,args);
}, 1);
var keys=Object.keys(obj);
var buildFuncWrapper=函数(i){
self[keys[i]]=函数(){
var args=Array.prototype.slice.call(参数);
变量任务={
func:keys[i],
args:args.slice(0,args.length-1),
cb:args.slice(args.length-1,args.length)[0]
};
q、 推送(任务、函数(){
if(global.DEBUG)console.log(“[SYNC WRAPPER]完成了对:”,key[i])的包装调用;
})
} 
}
var buildPropWrapper=函数(i){
Object.defineProperty(self,键[i]{
get:function(){returnobj[keys[i]]},
可写:false,
可枚举:true
})
}
对于(变量i=0;i
基本上,我可以将现有的API对象传递给它,它将通过队列转发对其函数的所有调用,因为队列的并发度为1,一次只处理一个调用


在这之后,只需确保此包装api对象只存在一个版本即可。

看起来您需要一个ajax包装器,将所有ajax请求添加到一个队列中,该队列一次执行一个请求。但是,这将对前端的性能产生影响。我对此并不太担心。前端上的每个帐户都将具有不同的API密钥,因此会有一系列单独的nonce。再加上traphic对于应用程序来说相对较低,api请求的数量每分钟不应该超过10个左右的api调用。但是是的,某种异步包装器将请求排队将是理想的。我只是不知道如何组织它。(不一定是ajax,因为它是一种仅用于浏览器的技术。)您将拥有某种形式的函数/模块/单例来执行ajax。结构非常依赖于您的代码如何使用所述函数以及应用程序的现有结构。我在一个示例中编辑了代码的结构。我将对该方法进行研究,它似乎可以满足您的需要。请注意,由于他使用的是
async
,有一个内置的方法可以创建这种队列。不过,这是一个不错的选择。
delete queue[0]
不是删除队列第一个元素的合法方法-请改用
var next=queue.shift()