// api.ts

let currentAbortController : AbortController | null = null
let currentCencel:(() => void) | null = null

export const fetchDifyWorkflow = async (params: any, onData:(data)=>void, onError:(error:Error) => void, onComplete?: () => void): Promise<() => void> => {
  // 取消之前的请求
  if (currentCencel) {
    currentCencel()
    currentAbortController?.abort()
  }
  
  currentAbortController= new AbortController();
  
  try {
    const response = await fetch(`${difyAPIUrl}?response_mode=streaming`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${difyAPIKey}`,
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(params),
        signal: currentAbortController.signal
    });

    if(!response.ok) {
        throw new Error(`status:${response.status}`)
    }
    if(!response.body) {
        throw new Error('readableStream not supported')
    }

    const reader = response.body?.getReader() // 用于获取HTTP请求体的字符流,返回BufferedReader对象
    const decoder = new TextDecoder() // 将二进制数据解码为文本字符串
    const buffer = ''

    const processData = async ():Promise<void> => {
        try {
            const {down, value} = await reader?.read()
            if(down) {
                onCompelet?.()
                return
            }    
            buffer += decoder.decode(value, { stream: true })

            const message = buffer.split('\n\n')    // 根据实际情况修改
            buffer = message.pop() || ''  // 保留不完整信息
    
            for (const msg of message) {
                if(msg.startWith('data:')){    // 根据实际情况修改
                    try{
                        const data = JSON.parse(msg.substring(6))
                        onData(data)
                    } catch (error) {
                        console.log('解析error',error)
                    }
                }
            }
            return processData()
        } catch (err) {
          // 主动取消不触发onError
          if(err instanceof Error) {  // TS4.4起,catch块默认unknown
             if ((err as Error).name !== 'AbortError) {
               onError?.(err)
             }
          } else {
             onError?.(new Error(String(err)))   
          } 
        }
     }
     processData()

    // 返回取消函数并保存引用
    const cancel = (): void => {
        reader.cancel()
        currentAbortController.abort()
    }

    currentCencel = cancel
    return currentCencel
  } catch (error) {
     if(err instanceof Error) {  // TS4.4起,catch块默认unknown
        if ((err as Error).name !== 'AbortError) {
          onError?.(err)
        }
     } else {
        onError?.(new Error(String(err)))   
     } 
     return () => {}
  }
}

export const cancelRequests = (): void => {
  if (currentCencel) {
    currentCencel()
    currentAbortController?.abort()
    currentCencel = null
    currentAbortController= null
  }
};

 

 

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐