request.js 4.12 KB
// zooble@2025-12-14

/**
 * 创建一个请求函数,该函数闭包了登录和重试逻辑
 * @param {object} baseConfig 基础配置
 * @param {string} baseConfig.domain API域名
 * @param {string} baseConfig.appid 小程序ID
 * @param {string} base.cid 渠道ID
 */
function createRequest(baseConfig) {
    let loginPromise = null;

    // 登录函数
    const login = () => {
        if (loginPromise) {
            return loginPromise;
        }

        const ssid = wx.getStorageSync('ssid');
        if (ssid) {
            return Promise.resolve(ssid);
        }

        wx.showLoading({ mask: true });

        loginPromise = new Promise((resolve, reject) => {
            wx.login({
                success: res => {
                    if (!res.code) {
                        const errorMsg = '登录失败:无法获取code';
                        wx.showModal({ title: '提示', content: errorMsg, showCancel: false });
                        return reject(new Error(errorMsg));
                    }

                    const { domain, appid } = baseConfig;
                    wx.request({
                        url: `${domain}/open-api/mp/login`,
                        data: { code: res.code, appid },
                        method: 'POST',
                        header: { 'content-type': 'application/json' },
                        dataType: 'json',
                        success: resp => {
                            const user = resp.data?.data?.user;
                            if (user && user.ssid) {
                                wx.setStorageSync('ssid', user.ssid);
                                wx.setStorageSync('openid', user.openid);
                                resolve(user.ssid);
                            } else {
                                const errorMsg = resp.data.msg || '登录失败:无效的用户信息';
                                wx.showModal({ title: '提示', content: errorMsg, showCancel: false });
                                reject(new Error(errorMsg));
                            }
                        },
                        fail: err => {
                            wx.showModal({ title: '提示', content: '登录请求失败', showCancel: false });
                            reject(err);
                        },
                        complete: () => {
                            wx.hideLoading();
                            loginPromise = null;
                        }
                    });
                },
                fail: err => {
                    wx.hideLoading();
                    loginPromise = null;
                    wx.showModal({ title: '提示', content: '微信登录失败', showCancel: false });
                    reject(err);
                }
            });
        });
        return loginPromise;
    };

    // 返回的请求函数
    const request = async (config) => {
        let ssid = wx.getStorageSync('ssid');
        if (!ssid) {
            try {
                ssid = await login();
            } catch (e) {
                if (config.fail) config.fail(e);
                // early return on login failure
                return;
            }
        }

        const finalConfig = {
            header: { 'content-type': 'application/json' },
            dataType: 'json',
            method: 'POST',
            ...config,
            data: {
                ...config.data,
                ssid,
                cid: baseConfig.cid,
            },
            success: (resp) => {
                // 登录态失效,自动重试
                if ([5001000, 5004000].includes(resp.data.code)) {
                    console.log('ssid expired, retrying request');
                    wx.setStorageSync('ssid', '');
                    // 传入原始 config 递归调用,避免 success 被多次包装
                    request(config);
                } else {
                    if (config.success) {
                        config.success(resp);
                    }
                }
            },
        };

        return wx.request(finalConfig);
    };

    return request;
};

module.exports = {
  createRequest
};