Skip to content
Advertisement

Unhandled promise rejection, even though I’m pretty sure I’ve handled them all

I’ve written a node app that fetches data from an API, using multiple endpoints. I am also using proxies to do this.

I’m currently using socks-proxy-agent to create a https agent for my axios instances to use the proxy.

Here is the class that does all of this:

export class Checker {
    private region: Region
    private proxy: AxiosProxyConfig | false
    private client: AxiosInstance
    constructor(region: Region, proxy?: AxiosProxyConfig | false) {
        this.region = region;
        this.proxy = proxy;
        if (proxy) {
            const proxyOptions = `socks://${proxy.host}:${proxy.port}`;
            const httpsAgent = new SocksProxyAgent(proxyOptions);
            this.client = axios.create({ timeout: 5000, httpsAgent: httpsAgent });
        } else {
            this.client = axios.create({ timeout: 5000 });
        }
    }
    public check(account: Account): Promise<CheckResponse> {
        return new Promise((resolve, reject) => {
            this.client.post("xxx", {
                acr_values: "urn:riot:bronze",
                claims: "",
                client_id: "riot-client",
                nonce: 1,
                redirect_uri: "http://localhost/redirect",
                response_type: "token id_token",
                scope: "openid link ban lol_region",
            }).then((response) => {
                const cookies = response.headers["set-cookie"];
                this.client.put(
                    "xxx",
                    {
                        type: "auth",
                        username: account.username,
                        password: account.password,
                        remember: false,
                        language: "en_GB",
                        region: this.region.login,
                    },
                    {
                        headers: {
                            Cookie: cookies,
                        },
                    }
                ).then(async (response) => {
                    //200 OK
                    const { data } = response;
                    if (data.error) {
                        //Error is present.
                        switch (data.error) {
                            case "auth_failure":
                                resolve({ type: CheckResponseType.INVALID });
                                break;
                            case "rate_limited":
                                reject({ type: CheckResponseType.RATE_LIMITED, proxy: this.proxy });
                                break;
                            default:
                                console.log("Unknown auth response error type: ", data.error)
                                reject({ type: CheckResponseType.RETRY });
                        }
                    } else {
                        //Login was successful - we can now get auth token and check champs etc.
                        const { uri } = data.response.parameters;
                        const access_token = /#access_token=(.*?)&/.exec(uri)[1] || null;
                        this.client.defaults.headers = {
                            Authorization: `Bearer ${access_token}`
                        }
                        this.client.post("xxx").then(async (response) => {
                            const userInfo = response.data;
                            const summoner: Summoner = {
                                account: account,
                                region: this.region,
                                id: userInfo.lol.cuid,
                                profileIcon: userInfo.lol_account.profile_icon,
                                name: userInfo.lol_account.summoner_name,
                                level: userInfo.lol_account.summoner_level,
                                emailVerified: userInfo.email_verified,
                                phoneVerified: userInfo.phone_number_verified
                            }
                            if (userInfo.ban.code) {
                                resolve({ type: CheckResponseType.BANNED });
                            } else {
                                try {
                                    const accountId = userInfo.lol.cuid;
                                    const inventory = await this.client.get(`xxx`);
                                    const champions = inventory.data.data.items.CHAMPION;
                                    const skins = inventory.data.data.items.CHAMPION_SKIN;
                                    const store = await this.client.get(`xxx`);
                                    const matchHistory = await this.client.get(`xxx`);
                                    const lastPlayed = matchHistory.data.games.games[0].gameCreation;
                                    summoner.data = {
                                        blueEssence: store.data.player.ip,
                                        riotPoints: store.data.player.rp,
                                        refunds: store.data.refundCreditsRemaining,
                                        champions: [],
                                        skins: [],
                                        lastPlayed: lastPlayed
                                    }
                                    champions.map((champion) => {
                                        summoner.data.champions.push({
                                            id: champion.itemId,
                                            purchaseDate: champion.purchaseDate
                                        });
                                    });
                                    skins.map((skin) => {
                                        summoner.data.skins.push({
                                            id: skin.itemId,
                                            purchaseDate: skin.purchaseDate,
                                            vintage: skin.payload.isVintage
                                        });
                                    });
                                    resolve({ type: CheckResponseType.SUCCESS, summoner: summoner });
                                } catch {
                                    reject({ type: CheckResponseType.RETRY });
                                }
                            }
                        });
                    }
                }).catch(() => {
                    reject({ type: CheckResponseType.RETRY });
                });
            }).catch(() => {
                reject({ type: CheckResponseType.RETRY });
            });
        });
    }
}

However, if there’s an issue with a proxy, I get unhandled promise rejections like this that seem to be coming from the socket:

(node:2200) UnhandledPromiseRejectionWarning: Error: connect ETIMEDOUT 46.101.212.177:9050
        at SocksClient.closeSocket (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:364:32)
        at SocksClient.onErrorHandler (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:337:14)
        at Socket.onError (C:NodeAppslol-crackernode_modulessocksbuildclientsocksclient.js:199:38)
        at Object.onceWrapper (events.js:422:26)
        at Socket.emit (events.js:315:20)
        at emitErrorNT (internal/streams/destroy.js:92:8)
        at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
        at processTicksAndRejections (internal/process/task_queues.js:84:21)
    (node:2200) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2266)
    (node:2200) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

However, I’m pretty sure I’ve handled everything. I even have a try/catch block around my await calls.

Advertisement

Answer

As I’m looking at your code this api call this.client.post("https://auth.riotgames.com/userinfo") doesn’t have catch function. By separating each one of your api calls in different functions and returning them, your code becomes much cleaner and finding these errors becomes easier.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement