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

React中如何在Axios的多个.then()链中传递非Promise变量?

解决React中Axios下载文件时文件名传递问题

问题原因

React的useState更新是异步的,调用setFileName和setExtension后,状态不会立即改变,而是要等到下一次组件渲染才会更新。所以在链式调用的下一个.then()里,你拿到的还是旧的空字符串状态。

解决方案

方案1:在链式调用中直接传递文件名变量

不需要依赖state来传递文件名,直接在第一个.then()里把解析好的文件名、扩展名和blob数据一起返回,下一个.then()接收这些值即可:

const [fileName, setFileName] = useState("")
const [extension, setExtension] = useState("")

const downloadFile = useCallback(async (path) => {
    Axios.get(
        `http://localhost:8080/api${path}`,
        { responseType: 'blob' })
        .then(res => {
            let headers = res.headers['content-disposition']
            let parsedFileName = headers.split('filename=')[1].split('.')[0]
            let parsedExtension = headers.split('.')[1].split(';')[0]

            setFileName(parsedFileName)
            setExtension(parsedExtension)

            // 返回包含blob和文件名信息的对象
            return {
                blob: res.data,
                fileName: parsedFileName,
                extension: parsedExtension
            }
        })
        .then(({ blob, fileName, extension }) => {
            const url = window.URL.createObjectURL(blob)
            const link = document.createElement('a')
            const fullFileName = `${fileName}.${extension}`

            link.href = url
            link.download = fullFileName;
            document.body.appendChild(link)
            link.click()
            link.remove()
            URL.revokeObjectURL(url)
        })
        .catch(err => console.log(err))
}, [])

方案2:合并两个.then()逻辑

既然文件名解析和下载操作是连续的,直接把它们放到同一个.then()里,避免链式传递的问题:

const [fileName, setFileName] = useState("")
const [extension, setExtension] = useState("")

const downloadFile = useCallback(async (path) => {
    Axios.get(
        `http://localhost:8080/api${path}`,
        { responseType: 'blob' })
        .then(res => {
            let headers = res.headers['content-disposition']
            let parsedFileName = headers.split('filename=')[1].split('.')[0]
            let parsedExtension = headers.split('.')[1].split(';')[0]

            setFileName(parsedFileName)
            setExtension(parsedExtension)

            // 直接在这里处理下载逻辑
            const blob = res.data
            const url = window.URL.createObjectURL(blob)
            const link = document.createElement('a')
            const fullFileName = `${parsedFileName}.${parsedExtension}`

            link.href = url
            link.download = fullFileName;
            document.body.appendChild(link)
            link.click()
            link.remove()
            URL.revokeObjectURL(url)
        })
        .catch(err => console.log(err))
}, [])

方案3:(不推荐)用useEffect监听状态变化

如果一定要依赖state来触发下载(比如需要根据状态变化做其他操作),可以用useEffect监听fileName和extension的变化,但这种方式会多一次渲染,不如直接传递变量高效:

const [fileName, setFileName] = useState("")
const [extension, setExtension] = useState("")
const [downloadBlob, setDownloadBlob] = useState(null)

// 监听状态变化触发下载
useEffect(() => {
    if (downloadBlob && fileName && extension) {
        const url = window.URL.createObjectURL(downloadBlob)
        const link = document.createElement('a')
        const fullFileName = `${fileName}.${extension}`

        link.href = url
        link.download = fullFileName;
        document.body.appendChild(link)
        link.click()
        link.remove()
        URL.revokeObjectURL(url)
        // 下载完成后清空blob
        setDownloadBlob(null)
    }
}, [downloadBlob, fileName, extension])

const downloadFile = useCallback(async (path) => {
    Axios.get(
        `http://localhost:8080/api${path}`,
        { responseType: 'blob' })
        .then(res => {
            let headers = res.headers['content-disposition']
            let parsedFileName = headers.split('filename=')[1].split('.')[0]
            let parsedExtension = headers.split('.')[1].split(';')[0]

            setFileName(parsedFileName)
            setExtension(parsedExtension)
            setDownloadBlob(res.data)
        })
        .catch(err => console.log(err))
}, [])

内容的提问来源于stack exchange,提问作者user28751094

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 13:13:19