javascript - 同步 异步进行 异步调用

标签 javascript node.js rest asynchronous synchronization

我被难住了

基本上,我有一个 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 对象对其收到的请求进行排队。

最佳答案

在 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);
        }
    }
}

基本上,我可以将现有的 API 对象传递给它,它会通过队列转发对其函数的所有调用,因为队列的并发度为 1,一次只会处理一个调用。

之后,确保此包装的 api 对象仅存在一个版本是一件相当简单的事情。

关于javascript - 同步 异步进行 异步调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24984299/

相关文章:

node.js - 如何在 node.js 中创建命名管道?

php - 如何使用 PHP HTTP 客户端执行基于证书的身份验证

javascript - Angular -Js : not able to access array elements in different function call within same controller

javascript - 来自 UTC + IANA 时区位置的时间

node.js - bcrypt CompareSync 始终返回 false

java - 泽西客户端握手错误

python - 当休息请求到达 flask 时如何更改元素的颜色(在 html 页面中)?

javascript - (JavaScript) 尝试通过复选框调用方法

javascript - 在 Node.JS 中排序数据

asp.net - 从 Node.js 将数据发布到 ASP.NET WEB API 服务