未处理的承诺拒绝,即使我很确定我已经处理了所有这些

Posted

技术标签:

【中文标题】未处理的承诺拒绝,即使我很确定我已经处理了所有这些【英文标题】:Unhandled promise rejection, even though I'm pretty sure I've handled them all 【发布时间】:2021-02-03 02:20:53 【问题描述】:

我编写了一个节点应用程序,它使用多个端点从 API 获取数据。我也在使用代理来做到这一点。

我目前正在使用 socks-proxy-agent 为我的 axios 实例创建一个 https 代理以使用代理。

这是执行所有这些操作的类:

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

但是,如果代理出现问题,我会收到类似这样的未处理的 Promise 拒绝,似乎来自套接字:

(node:2200) UnhandledPromiseRejectionWarning: Error: connect ETIMEDOUT 46.101.212.177:9050
        at SocksClient.closeSocket (C:\NodeApps\lol-cracker\node_modules\socks\build\client\socksclient.js:364:32)
        at SocksClient.onErrorHandler (C:\NodeApps\lol-cracker\node_modules\socks\build\client\socksclient.js:337:14)
        at Socket.onError (C:\NodeApps\lol-cracker\node_modules\socks\build\client\socksclient.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.

但是,我很确定我已经处理了所有事情。我什至在我的等待调用周围有一个 try/catch 块。

【问题讨论】:

代码看起来很吵,你能尝试遵循正确的承诺链吗?您有嵌套的承诺,这导致了问题尝试重构并尝试将函数分解为小的承诺函数并创建正确的承诺链 【参考方案1】:

当我查看您的代码时,此 api 调用 this.client.post("https://auth.riotgames.com/userinfo") 没有 catch 函数。 通过在不同的函数中分离每个 api 调用并返回它们,您的代码会变得更加简洁,并且更容易发现这些错误。

【讨论】:

噢!我不敢相信我错过了。只是为了显示代码是多么混乱,很容易错过这样的东西。 @ThePerplexedOne 很高兴为您提供帮助。如果它解决了您的问题,请标记为答案:)

以上是关于未处理的承诺拒绝,即使我很确定我已经处理了所有这些的主要内容,如果未能解决你的问题,请参考以下文章

可能未处理的承诺拒绝未定义不是一个函数

redux 操作功能无法正确执行 - expo“可能未处理的承诺拒绝”

使用 useMutation 可能出现未处理的承诺拒绝警告

未处理的承诺拒绝条带支付意图示例

反应本机中未处理的承诺拒绝错误?

未处理的承诺拒绝:错误:URL 格式错误,无法解析