繁体   English   中英

在 Javascript 中为回调函数添加一个额外的参数

[英]Add an extra parameter to a callback function in Javascript

您好 Stackoverflow 用户,

许多像我这样的人都在搜索如何将额外的参数传递给回调函数。 这些问题的标题相似,但实际上它们具有不同的挑战和许多解决方法。 另外,分享实践以增加经验总是很高兴。

最近,我在我的 node js 项目中遇到了一个非常简单的挑战。 我与之通信的其中一个 API 有一个同步工作的 SDK。 而且我曾经每次都传递回调函数(当您有相互依赖的请求并且需要在应用程序层内传输一些数据时,这很烦人)。

想象一下这样的计划支付流程,客户端向服务器发送一个请求,其中包括所选计划和他的 ID。 服务器 API 层收到请求数据后,会将其传递给第三方服务函数( .create(...) )。 第三方服务函数接收带有 2 个参数function(err, plan_document)的回调。 然后,回调应该通过请求中的 ID 将选定的计划逻辑应用于客户端。

** 我们需要将客户端和计划的数据传递给回调函数以应用逻辑。 第三方服务为回调提供了一个 plan_document 参数,我们仍然需要以某种方式将客户端 ID 从 API 层传递给服务。

代码将如下所示。

const create_plan_agreement = (req, res) => {
    // some code
    var client_id = req.auth.client_id;
    third_party.plan_agreement.create({}, update_plan_agreement);
};
const update_plan_agreement = (err, plan_document, client_id) => {
    /* 
        The third-party `third_party.plan_agreement.create` function passes the first 
        two parameters and somehow we need to add the client_id 
    */
    console.log('client plan activated');
    active_client_plan(plan_document, client_id);
};

- - - - - - - - - 编辑 - - - - - - - - -

我想知道如果流程更长并且我需要客户端 ID 比这样的更新功能更远怎么办。

const create_plan_agreement = (req, res) => {
    // some code
    var client_id = req.auth.client_id;
    third_party.plan_agreement.create({}, update_plan_agreement);
};
const update_plan_agreement = (err, plan_document) => {
    console.log('plan activated, send notification to the client');
    third_party.plan_agreement.update(plan_document, send_agreement_notification);
};
const send_agreement_notification = (err, plan_document) => {
    console.log('client plan activated');
    active_client_plan(plan_document, this.client_id);
};

在这种情况下我该怎么办? 我是否应该一直重复.bind({'client_id': client_id})函数,直到流程的最后一步?

如果您想支持老年人,您可以使用包含回调轻松绑定,如下所示:

 const create_plan_agreement = (req, res) => { // some code var client_id = req.auth.client_id; third_party.plan_agreement.create({}, function(params, from, create) { update_plan_agreement(params, from, create, client_id) }); }; const update_plan_agreement = (err, plan_document, client_id) => { /* The third-party `third_party.plan_agreement.create` function passes the first two parameters and somehow we need to add the client_id */ console.log('client plan activated'); active_client_plan(plan_document, client_id); };

传统的方法是使用闭包。 在父范围内定义函数,以便它们可以将client_id作为封闭变量(有点像全局变量)访问:

const create_plan_agreement = (req, res) => {
    // some code
    var client_id = req.auth.client_id;


    const update_plan_agreement = (err, plan_document) => {
        console.log('plan activated, send notification to the client');
        third_party.plan_agreement.update(plan_document, send_agreement_notification);
    };

    const send_agreement_notification = (err, plan_document) => {
        console.log('client plan activated');

        // Note: this function can access client_id
        // because it is in scope
        active_client_plan(plan_document, client_id);
    };

    third_party.plan_agreement.create({}, update_plan_agreement);
};

闭包之于作用域就像对象之于类。 闭包是作用域的一个实例 因此,与常规全局变量不同,每次调用create_plan_agreement()都会使用自己的client_id副本创建自己的闭包。

使用现代 javascript,通常使用Promise更容易处理这个问题。 转换遗留函数以返回Promise ,然后您可以使用async/await

const create_plan_agreement = async (req, res) => {
    // some code
    var client_id = req.auth.client_id;
    try {
        var plan_document = await plan_agreement_create({});
        var updated_plan_document = await update_plan_agreement(plan_document);
        send_agreement_notification(updated_plan_document, client_id);
    }
    catch (err) {
        // handle errors here.
    }
};

const plan_agreement_create = (arg) {
    return new Promise ((ok, fail) => {
        third_party.plan_agreement.create({}, (err, result) => {
            if (err) {
                return fail(err);
            }
            ok(result);
        });
    })
}

const update_plan_agreement = (plan_document) => {
    return new Promise ((ok, fail) => {
        third_party.plan_agreement.update(plan_document, (err, result) => {
            if (err) return fail(err);
            ok(result);
        });
    });
};

const send_agreement_notification = (plan_document, client_id) => {
    active_client_plan(plan_document, client_id);
};

或者即使没有async/await Promise仍然使回调更易于使用:

const create_plan_agreement = async (req, res) => {
    // some code
    var client_id = req.auth.client_id;

    plan_agreement_create({})
        .then(doc => update_plan_agreement(doc));
        .then(doc => {
            send_agreement_notification(doc, client_id)
        })
        .catch(err => {
            // handle errors here.
        });
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM