Amis中传入用户自定义fetcher(基于fetcher做接口调用):
1.embed渲染时可以传入用户定义的fetcher(接口调用):
import axios from "@/libs/api.request"; //自定义的fetcher调用接口(axios调用) { fetcher: ()=>{ ……; return (axios)[method](url, data, config) } }let tracker = (eventTrack, props) => {if (eventTrack.eventType == 'formItemChange') {self.$nextTick(() => {self.nodeUpdate = false;self.submitNode();});}}amisEnv.tracker = tracker;amisEnv.session = "global"self.amisScoped = amis.embed(self.$refs['mpageconfig'], amisJSON, {data: {mdata: this.gisTreeNames}}, amisEnv); // fetcher 接口
2.后续还可以用updateEnv更新用户自定义的fetcher:
updateEnv(options: Partial<RenderOptions>, session = 'global') {
源码解析:
1.wrapFetcher的使用(封装用户传入的fetcher调用)
amis-core/index.ts:
if (!store) { //options = {...defaultOptions,...options,fetcher: options.fetcher? wrapFetcher(options.fetcher, options.tracker) // options.fetcher用户自行实现的接口调用逻辑。: defaultOptions.fetcher,confirm: promisify(options.confirm || defaultOptions.confirm || window.confirm),locale,translate} as any;
}
2.wrapFetcher 方法源码(封装fetcher):
主要进行了如下操作:
(1).调用buildApi() 进行api.data 映射解析,和adaptor requestAdator函数封装
(2).调用api.requestAdaptor() 请求适配器函数
(3).调用wrapAdaptor 执行adaptor并进行api.responseData映射解析
Amis-core/uitls/api.ts:
export function wrapFetcher(fn: (config: fetcherConfig) => Promise<fetcherResult>,tracker?: (eventTrack: EventTrack, data: any) => void
): (api: Api, data: object, options?: object) => Promise<Payload | void> { // 返回一个api处理调用函数return function (api, data, options) {
let api = buildApi(api, data, options) // api:接口参数 data数据域 。 封装requestAdaptor, adaptor函数(new Function) 对dataType, cache(缓存到组件内apiCaches数组里)等进行处理
api = api.requestAdaptor(api) || api; //调用api.requestAdaptor请求适配器函数//…省略return wrapAdaptor(fn(api), api); // 调用api.adaptor响应适配器处理. 处理后会将ret交给amis内置的responseAdaptor函数进行数据解析(JSON.parse)和api.responseData映射。}}
3.buildApi源码(api.data 映射解析,adaptor requestAdator函数封装):
Amis-core/uitls/api.ts:
export function buildApi( api: Api, data?: object, options: { autoAppend?: boolean; ignoreData?: boolean; [propName: string]: any; } = {} ): ApiObject { //api:接口参数 data:数据域..省略//主要封装adaptor requestAdator函数(new Function)、 解析headers method参数if (!data) {return api;}else if( data instanceof FormData || data instanceof Blob || data instanceof ArrayBuffer ) {api.data = data; //数据域数据是表单类型或文件类型 则将数据域直接赋值给api.data(ps:即数据域默认作为url参数全部传递)return api;}… //各种处理if (api.data) {api.body = api.data = dataMapping( api.data, data, undefined, api.convertKeyToPath ); //dataMapping(to,from),会判断from若是object类型(isPlainObject)则from也set到ret中,否则只将to set到ret中(from只作为表达式解析resolveMapping的数据域使用)} else if (api.method === 'post' ||api.method === 'put' ||api.method === 'patch') {api.body = api.data = cloneObject(data);}
}
3.wrapAdaptor源码(执行adaptor并api.responseData映射解析):
Amis-core/uitls/api.ts:
export function wrapAdaptor(promise: Promise<fetcherResult>, api: ApiObject) {const adaptor = api.adaptor;return adaptor? promise.then(async response => {debug('api', 'before adaptor data', (response as any).data);let result = adaptor((response as any).data, response, api);if (result?.then) {result = await result;}debug('api', 'after adaptor data', result);return {...response,data: result};}).then(ret => responseAdaptor(ret, api)): promise.then(ret => responseAdaptor(ret, api));
}export function responseAdaptor(ret: fetcherResult, api: ApiObject) {...//进行数据解析(JSON.parse escapeHtml)等const payload: Payload = {ok: hasStatusField === false || data.status == 0,status: hasStatusField === false ? 0 : data.status,msg: data.msg || data.message,defaultMsg: data.defaultMsg,msgTimeout: data.msgTimeout,data: !data.data && !hasStatusField ? data : data.data // 兼容直接返回数据的情况};if (payload.ok && api.responseData) {debug('api', 'before dataMapping', payload.data);const responseData = dataMapping( //responseData 映射处理。 dataMapping(to,from),会判断from若是object类型(isPlainObject)则from也set到ret中,否则只将to set到ret中api.responseData,createObject({ api },(Array.isArray(payload.data)? {items: payload.data}: payload.data) || {}),undefined,api.convertKeyToPath);payload.data = responseData;
}