Cenas
-
Recentemente, estou usando uni-app para desenvolver o terminal móvel H5. Como de costume, uso axios para enviar solicitações e fazer algumas operações globais de interceptação de solicitação e interceptação de resposta.
-
armazenamento de dados uni-app, desenvolvimento de componentes uni-ui, configuração de axios, vuex. O arquivo vue.config.js está configurado para operações entre domínios
-
Tudo funciona bem ao executar no Google Chrome, mas ao executar nas ferramentas do desenvolvedor WeChat, um erro é relatado, o Adaptador-adaptador não está disponível e a solicitação não pode ser enviada.
-
Por fim, após uma pesquisa na Internet, descobri que a resposta é a mesma, e o problema não foi resolvido, e demorou muito para resolver o problema.
Relatório de erro - o adaptador "http" não está disponível no buildat ObjectgetAdapter - a solicitação não é enviada
entenda por si mesmo
1. Muitas pessoas dizem que o axios não é compatível com o uni-app. Esse tipo de declaração é relativamente apressado. Na verdade, o uni-app também pode ser compatível com o axios após a modificação.
1. O Axios é baseado na camada de encapsulamento acima do AJax, e o princípio é enviar solicitações por meio de objetos minion
2. Nas ferramentas do desenvolvedor do WeChat, o ambiente do WeChat pode ter desativado o método de gravação de envio de solicitações na parte inferior do minion, resultando no não envio da solicitação e no erro não encontrado
3. A solução online é escrever um adaptador para axios no main.js ou request.js onde o axios é introduzido - ou alterar a versão
4. Esse método não resolve fundamentalmente o problema. Outro erro será relatado se a solicitação não for enviada. A URL de compilação está vazia e não pode ser encontrada.
Resolução de erro - se a solicitação não puder ser enviada, outro erro será reportado
Escreva um adaptador onde o axios é introduzido
// 解决uni-app Adapter为空问题
// axios.defaults.adapter = function(config) {
// return new Promise((resolve, reject) => {
// var settle = require('axios/lib/core/settle');
// var buildURL = require('axios/lib/helpers/buildURL');
// uni.request({
// method: config.method.toUpperCase(),
// url: config.baseURL + buildURL(config.url, config.params, config.paramsSerializer),
// header: config.headers,
// data: config.data,
// dataType: config.dataType,
// responseType: config.responseType,
// sslVerify: config.sslVerify,
// complete: function complete(response) {
// response = {
// data: response.data,
// status: response.statusCode,
// errMsg: response.errMsg,
// header: response.header,
// config: config
// };
// settle(resolve, reject, response);
// }
// })
// })
// }
resultado
Interpretação da cena atual
1. Por que não usar uni.request() fornecido pelo site oficial do aplicativo uni, porque ele não fornece interceptação de solicitação e interceptação de resposta, o que não é satisfatório.
2.uni-app usa axios para fazer solicitações
2.1 Ao executar o Google Chrome
-
Somos um ambiente node.js, precisamos configurar o endereço base node.js, interceptação de solicitação e interceptação de resposta em request.js como de costume
-
Defina variáveis de ambiente globais no arquivo vue.config.js, e o arquivo global no site oficial do uni-app tem escrita de modelo
-
Por ser um navegador que precisa de cross-domain, também é necessário configurar cross-domain no vue.config.js
-
Por que usar o armazenamento de dados uni-app, porque o princípio de usar o armazenamento de dados uni-app é o armazenamento do navegador.
-
O armazenamento do navegador uni-app pode ser usado normalmente no Google Chrome, mas o armazenamento do navegador não pode ser usado nas ferramentas do desenvolvedor do WeChat, não é compatível
-
O arquivo vue.config.js define variáveis globais - há exemplos no arquivo global no site oficial
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
args[0]['process.env'].VUE_APP_BASE_API = '"/dev-api"'
return args
})
}
2.2 Ao executar WeChat para ferramentas de desenvolvedor
-
Por ser uma ferramenta de desenvolvedor WeChat e um ambiente WeChat, não há domínio cruzado, o arquivo vue.config.js será inválido e o proxy será descartado
-
Como o ambiente WeChat não é compatível com axios, a solicitação não pode ser enviada e um erro será relatado - há uma solução abaixo
-
No ambiente WeChat, o endereço base em nosso arquivo request.js não pode ser escrito como uma variável global, mas deve ser escrito como uma string ip+port
solução correta
1. Substitua todos os axios, use o pacote de terceiros @escook/request-miniprogram semelhante ao axios
-
Você pode acessar o site oficial do npm para procurar este pacote e encontrará o uso detalhado deste pacote ao rolar para baixo.
-
Este método é usado apenas quando o problema do axios não pode ser resolvido, não o recomendamos aqui - há uma solução do axios abaixo
Código básico - crie requesthttp.js em utils e introduza-o em main.js (semelhante ao uso de axios - consulte os detalhes
// 按需导入 $http 请求对象
import { $http } from '@escook/request-miniprogram'
// 将按需导入的 $http 挂载到 wx 顶级对象之上,方便全局调用
// wx这个东西是微信小程序里的顶级对象,也就是说所有页面都可以访问wx这个对象
// 所以我所有地方就可以用 wx.$http访问到请求对象了
// wx.$http = $http
// 设置基地址
$http.baseUrl = 'https://api-hmugo-web.itheima.net/api/public/v1/'
// process.env.VUE_APP_BASE_API
// 在 uni-app 项目中,可以把 $http 挂载到 uni 顶级对象之上,方便全局调用
// 小程序里wx是顶级对象,但是在uniapp中,uni才是顶级对象
uni.$http = $http
// 请求开始之前做一些事情
// 因为咱们是uniapp项目,顶级对象不叫wx,叫uni,记得把wx这个改成uni
$http.beforeRequest = function (options) {
uni.showLoading({
title: '数据加载中...',
})
}
// 请求完成之后做一些事情
$http.afterRequest = function () {
uni.hideLoading()
}
2. Continue a usar axios para ser compatível com o ambiente WeChat - com a ajuda de pacotes de terceiros
2.1 Precauções
-
Este método é testado pelo blogueiro e pode resolver o problema. Certifique-se de lê-lo passo a passo. Não se preocupe.
-
Às vezes, as ferramentas de desenvolvedor uni-app e WeChat apresentam bugs, lembre-se de fechar e reabrir a compilação
-
Outro pacote é baixado com base no axios, sem controlar a versão do axios, um arquivo createError.js precisa ser adicionado ao pacote do axios.
2.2 Implementação específica
2.2.1 Baixar axios-miniprogram-adapter no Hbuilder X
npm i axios-miniprogram-adapter
2.2.2 Visualize o pacote de arquivos lib/core/ sob o pacote axios no projeto node_model
2.2.3 Adicione a seguinte configuração no arquivo request.js
import adapter from 'axios-miniprogram-adapter'
// 设置基地址
const request = axios.create({
// 运行到浏览器时,把这一行注释回来,VUE_APP_BASE_API是在vue.config.js中配置的,官网有
// baseURL: process.env.VUE_APP_BASE_API,
// 运行到浏览器时下面一行注释掉
baseURL: 'http://127.0.0.1:8800',
// 在微信开发者工具环境中,axios,http是发不出去的,没有跨域,vue.config.js文件也是无效的
// 基于axios-miniprogram-adapter包给axios中添加一个适配器
// 运行到浏览器时,下面一行注释掉,axios时可以在浏览器中正常使用的,不需要适配器
adapter: adapter,
})
2.2.4 Ao executar de uni-app para ferramentas de desenvolvedor WeChat, o Hbuilder X relatará um erro
2.2.5 O relatório de erro significa que axios-miniprogram-adapter está referenciando o pacote em axios. Axios não possui este pacote e não pode encontrá-lo. Você pode clicar no relatório de erro abaixo para visualizá-lo na pasta correspondente
2.2.6 Crie um pacote createError.js em axios/lib/core para axios-miniprogram-adapter para resolver o problema
-
Venha para este diretório para criar o arquivo createError.js
-
Copie o conteúdo do arquivo AxiosError.js diretamente para o arquivo createError.js
2.2.7 Execute novamente o projeto para a ferramenta de desenvolvedor WeChat no Hbuilder X e descubra que não há erro, axios podem ser usados e a solicitação é enviada
2.2.8 código completo request.js - apenas para referência, é melhor não copiar
import axios from 'axios'
import adapter from 'axios-miniprogram-adapter'
// 引入vuex
import store from '@/store'
// 解决uni-app Adapter为空问题-不可行解决不了
// axios.defaults.adapter = function(config) {
// return new Promise((resolve, reject) => {
// var settle = require('axios/lib/core/settle');
// var buildURL = require('axios/lib/helpers/buildURL');
// uni.request({
// method: config.method.toUpperCase(),
// url: config.baseURL + buildURL(config.url, config.params, config.paramsSerializer),
// header: config.headers,
// data: config.data,
// dataType: config.dataType,
// responseType: config.responseType,
// sslVerify: config.sslVerify,
// complete: function complete(response) {
// response = {
// data: response.data,
// status: response.statusCode,
// errMsg: response.errMsg,
// header: response.header,
// config: config
// };
// settle(resolve, reject, response);
// }
// })
// })
// }
// 设置基地址
const request = axios.create({
// 运行到浏览器时,把这一行注释回来,VUE_APP_BASE_API是在vue.config.js中配置的,官网有
// baseURL: process.env.VUE_APP_BASE_API,
// 运行到浏览器时下面一行注释掉
baseURL: 'http://127.0.0.1:8800',
// 在微信开发者工具环境中,axios,http是发不出去的,没有跨域,vue.config.js文件也是无效的
// 基于axios-miniprogram-adapter包给axios中添加一个适配器
// 运行到浏览器时,下面一行注释掉,axios时可以在浏览器中正常使用的,不需要适配器
adapter: adapter,
})
// 解决UNI-app上adapter is not a function问题
axios.defaults.adapter = function(config) {
return new Promise((resolve, reject) => {
console.log(config)
var settle = require('axios/lib/core/settle');
var buildURL = require('axios/lib/helpers/buildURL');
uni.request({
method: config.method.toUpperCase(),
url: config.baseURL + buildURL(config.url, config.params, config.paramsSerializer),
header: config.headers,
data: config.data,
dataType: config.dataType,
responseType: config.responseType,
sslVerify: config.sslVerify,
complete: function complete(response) {
response = {
data: response.data,
status: response.statusCode,
errMsg: response.errMsg,
header: response.header,
config: config
};
settle(resolve, reject, response);
}
})
})
}
// 请求拦截
request.interceptors.request.use(
config => {
console.log('store.getters.token', store.getters.token);
if (store.getters.token) {
console.log('执行了');
// config.headers['token'] = getToken()
// config.headers['tenant-id'] = getuserId()
// 建议使用uni-app数据同步存储,在谷歌浏览器可以用,但是谷歌浏览器储存在微信开发者工具用了
config.headers['token'] = uni.getStorageSync('token')
config.headers['tenant-id'] = uni.getStorageSync('tenant-id')
}
return config
},
error => {
return Promise.reject(error)
}
)
// 响应拦截
request.interceptors.response.use(
res => {
const data = res.data
if (data.code === 200) {
// 如果响应成功,则正常给他返回数据
return data
} else {
uni.$showToast(data.message)
return Promise.reject(new Error(data.message))
}
},
// 响应错误的代码写这里
async error => {
// 打印错误拦截的信息
console.log('响应拦截error', error)
// error.response 这个是浏览器语法错误返回信息
// error.response.data 这个是接口返回错误信息 固定写法 看打印
if (error.response && error.response.data) {
// token失效携带页面参数返回登录页
if (error.response.status === 401) {
// vuex退出登录方法
} else {
console.log(error.response.data.message);
uni.$showToast('请求错误')
}
}
return Promise.reject(error)
}
)
// 把对象暴露出去
export default request
Resumir:
Após as operações acima, o axios pode ser compatível com ferramentas de desenvolvedor uni-app e satélite. Só precisamos mudar a configuração de endereço base ao enviar para o navegador e ferramentas de desenvolvedor WeChat, e ambas as extremidades podem ser adaptadas.
Após esse processo, acredito que você também tenha uma impressão profunda preliminar no uni-app usando axios para enviar uma solicitação de execução para a ferramenta de desenvolvedor WeChat para relatar um erro Adaptador "http' não está disponível na compilação, mas no desenvolvimento real encontramos A situação é definitivamente diferente, então temos que entender seus princípios e manter o mesmo princípio. Vamos, vença os trabalhadores!
Por favor, aponte quaisquer deficiências, obrigado -- Fengguowuhen