簡體   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