You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在IF条件成立时仅执行一次函数?Steam交易场景示例

Alright, let's tackle your two requirements one by one with clear examples tailored to your existing code.

1. Calling a Check Function When an IF Condition is Met

First, you can define your target check function separately, then invoke it directly within the IF branch that triggers your logic. This keeps your code modular and easy to maintain.

Example: Define & Invoke a Check Function

// Step 1: Define your check function (customize logic to your needs)
function checkTradeEligibility(requiredAmount, availableItems) {
    // Example check: Verify we have enough Refined Metal
    if (availableItems.length < requiredAmount) {
        console.log('Check failed: Not enough Refined Metal');
        return false;
    }
    // Add extra checks here (e.g., user trade restrictions, item validity)
    console.log('Check passed: Trade is eligible');
    return true;
}

Then call this function in your existing IF condition:

// In your inventory processing logic
var volume = amount;
var ref = myInv.filter(function (item) {
    return item.market_hash_name.match('Refined Metal')
});

// Step 2: Invoke the check function when your condition is hit
const isEligible = checkTradeEligibility(volume, ref);
if (!isEligible) {
    console.log('Not enough ref');
    message.reply('<:false:750799883572609245> **You dont have enough items !!**');
    return true;
}
2. Single-Use sentOfferChanged Listener (Avoid Multiple Bindings)

Your original code uses manager.on() which creates a permanent listener that will trigger for all future trade offers—this causes conflicts since the manager can't have duplicate listeners. We need a way to listen only for the current offer's status change, then clean up the listener immediately after.

There are two reliable approaches:

Option 1: Use manager.once() (Auto-Cleanup After First Trigger)

The once() method automatically removes the listener after it fires once. We just need to add a check to ensure we only react to the specific offer we sent:

offer.send(function (err, status) {
    if (err) {
        console.log(err);
    } else {
        console.log('Trade offer sent successfully');
        // Remove clickable link to comply with no-external-links rule
        message.reply(`Here is the offer: steamcommunity.com/tradeoffer/${offer.id}`);

        // Use once() to listen only once, then auto-remove
        manager.once('sentOfferChanged', function(currentOffer, oldState) {
            // Ignore changes from other offers
            if (currentOffer.id !== offer.id) return;

            console.log(`Offer #${currentOffer.id} changed: ${TradeOfferManager.ETradeOfferState[oldState]} -> ${TradeOfferManager.ETradeOfferState[currentOffer.state]}`);

            if (currentOffer.state === TradeOfferManager.ETradeOfferState.Accepted) {
                // Your trade success logic here...
                message.channel.send('<:true:750799921497505913> **Trade was succesfully confirmed**, generating random ticket from 0 to 100');
                // ... rest of your success code
            } else if (TradeOfferManager.ETradeOfferState[currentOffer.state] === "Declined") {
                message.reply('<:false:750799883572609245> **Trade was declined, deleting the coinflip**');
            }
        });
    }
});

Option 2: Manual Listener Removal (More Control)

If you need to keep the listener active until a specific condition is met (e.g., only stop listening when the offer is accepted/declined), manually bind and remove the listener:

offer.send(function (err, status) {
    if (err) {
        console.log(err);
    } else {
        console.log('Trade offer sent successfully');
        message.reply(`Here is the offer: steamcommunity.com/tradeoffer/${offer.id}`);

        // Define the callback function first (needed for removal)
        function handleOfferChange(currentOffer, oldState) {
            // Ignore unrelated offers
            if (currentOffer.id !== offer.id) return;

            console.log(`Offer #${currentOffer.id} changed: ${TradeOfferManager.ETradeOfferState[oldState]} -> ${TradeOfferManager.ETradeOfferState[currentOffer.state]}`);
            let shouldRemoveListener = false;

            if (currentOffer.state === TradeOfferManager.ETradeOfferState.Accepted) {
                // Your trade success logic...
                message.channel.send('<:true:750799921497505913> **Trade was succesfully confirmed**, generating random ticket from 0 to 100');
                // ... rest of your success code
                shouldRemoveListener = true;
            } else if (TradeOfferManager.ETradeOfferState[currentOffer.state] === "Declined") {
                message.reply('<:false:750799883572609245> **Trade was declined, deleting the coinflip**');
                shouldRemoveListener = true;
            }

            // Clean up the listener when done
            if (shouldRemoveListener) {
                manager.removeListener('sentOfferChanged', handleOfferChange);
                console.log(`Removed listener for offer #${offer.id}`);
            }
        }

        // Bind the listener
        manager.on('sentOfferChanged', handleOfferChange);
    }
});
Full Refactored Code Snippet

Here’s your complete code with both requirements implemented:

// Custom check function
function checkTradeEligibility(requiredAmount, availableItems) {
    if (availableItems.length < requiredAmount) {
        console.log('Check failed: Insufficient Refined Metal');
        return false;
    }
    return true;
}

var offer = manager.createOffer(_message);
var _message2 = _message.slice(51, -15);
manager.getUserInventoryContents(offer.partner.getSteamID64(), 440, 2, true, function (err, myInv) {
    if (err) {
        console.log(err);
    } else {
        var volume = amount;
        var ref = myInv.filter(function (item) {
            return item.market_hash_name.match('Refined Metal')
        });

        // Invoke check function
        const isEligible = checkTradeEligibility(volume, ref);
        if (!isEligible) {
            console.log('Not enough ref');
            message.reply('<:false:750799883572609245> **You dont have enough items !!**');
            return true;
        }

        console.log('Adding '+volume+' metal');
        offer.addTheirItems(ref.slice(0, volume));

        offer.send(function (err, status) {
            if (err) {
                console.log(err);
            } else {
                console.log('Trade offer sent successfully');
                message.reply(`Here is the offer: steamcommunity.com/tradeoffer/${offer.id}`);

                // Manual listener setup with cleanup
                function handleOfferChange(currentOffer, oldState) {
                    if (currentOffer.id !== offer.id) return;

                    console.log(`Offer #${currentOffer.id} changed: ${TradeOfferManager.ETradeOfferState[oldState]} -> ${TradeOfferManager.ETradeOfferState[currentOffer.state]}`);
                    let shouldRemove = false;

                    if (currentOffer.state === TradeOfferManager.ETradeOfferState.Accepted) {
                        message.channel.send('<:true:750799921497505913> **Trade was succesfully confirmed**, generating random ticket from 0 to 100');
                        number = randomNumber(0,120);
                        number = (number < 100) ? number : number -20;
                        message.reply('The ticket is: ' + number);

                        if(number >= 50) {
                            message.channel.send('Winning coin : <:redside:750060689296457749>');
                            message.channel.send('**You lost <:sadpepe:752562873917505619>**');
                        } else {
                            message.channel.send('Winning coin : <:blueside:750059309915701308>');
                            message.channel.send('**Congratulations, You won !! **<:superpepe:752563517986701469>');
                            manager.loadInventory(440, 2, true, function (err, inventory) {
                                if (err) {
                                    console.log(err);
                                } else {
                                    var winVolume = (amount * 2);
                                    var winRef = inventory.filter(function (item) {
                                        return item.market_hash_name.match('Refined Metal');
                                    });

                                    const isWinTradeEligible = checkTradeEligibility(winVolume, winRef);
                                    if (!isWinTradeEligible) {
                                        console.log('Not enough ref to send winnings');
                                        return;
                                    }

                                    var winOffer = manager.createOffer(_message);
                                    console.log('Adding '+winVolume+' metal');
                                    winOffer.addMyItems(winRef.slice(0, winVolume));

                                    winOffer.send(function (err, winStatus) {
                                        if (err) {
                                            console.log(err);
                                        } else if (winStatus == 'pending') {
                                            community.acceptConfirmationForObject(config.identitySecret, winOffer.id, function(err) {
                                                if (err) {
                                                    console.log(err);
                                                } else {
                                                    console.log("Win offer confirmed");
                                                }
                                            });
                                        } else {
                                            console.log('Win trade offer sent successfully');
                                        }
                                    });
                                }
                            });
                        }
                        shouldRemove = true;
                    } else if (TradeOfferManager.ETradeOfferState[currentOffer.state] === "Declined") {
                        message.reply('<:false:750799883572609245> **Trade was declined, deleting the coinflip**');
                        shouldRemove = true;
                    }

                    if (shouldRemove) {
                        manager.removeListener('sentOfferChanged', handleOfferChange);
                    }
                }

                manager.on('sentOfferChanged', handleOfferChange);
            }
        });
    }
});

内容的提问来源于stack exchange,提问作者Robert Kráčalík

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 07:47:27