シーン
-
最近、uni-app を使用して H5 モバイル端末を開発していますが、いつものように axios を使用してリクエストを送信し、グローバルなリクエスト インターセプトとレスポンス インターセプトの操作を行っています。
-
uni-app データストレージ、uni-ui コンポーネント開発、axios の設定、vuex。vue.config.js ファイルはクロスドメイン操作用に構成されています
-
Google Chrome で実行する場合はすべて正常に動作しますが、WeChat 開発者ツールで実行するとエラーが報告され、アダプターアダプターが使用できなくなり、リクエストを送信できません。
-
最後にインターネットで調べてみると、答えは同じで問題は解決されておらず、問題解決に時間がかかりました。
エラー レポート - アダプター "http" はビルド ObjectgetAdapter で使用できません - リクエストはまったく送信されません
自分で理解する
1. axios は uni-app と互換性がないという意見がよくありますが、この種の発言は比較的性急であり、実際には uni-app を修正すれば、axios と互換性を持たせることもできます。
1. Axios は AJax 上のカプセル化層に基づいており、原理はミニオン オブジェクトを通じてリクエストを送信することです。
2. WeChat 開発者ツールでは、WeChat 環境がミニオンの下部でリクエストを送信する書き込みメソッドを無効にしている可能性があり、その結果リクエストが送信されず、エラーが見つからない
3. オンラインの解決策は、axios が導入されている main.js または request.js に axios 用のアダプターを記述するか、バージョンを変更することです。
4. この方法では問題が根本的に解決されるわけではありません。リクエストが送信されない場合は、ビルド URL が空で見つからないという別のエラーが報告されます。
エラー解決 - リクエストを送信できない場合は、別のエラーが報告されます。
axios を導入するアダプターを作成する
// 解决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);
// }
// })
// })
// }
結果
現在のシーンの解釈
1. uni-app 公式 Web サイトが提供する uni.request() を使用してみてはいかがでしょうか。リクエストのインターセプトとレスポンスのインターセプトが提供されていないため、満足のいくものではありません。
2.uni-app は axios を使用してリクエストを行います
2.1 Google Chromeを実行している場合
-
私たちはnode.js環境です。通常どおり、request.jsでnode.jsのベースアドレス、リクエストのインターセプト、およびレスポンスのインターセプトを構成する必要があります。
-
vue.config.jsファイルにグローバル環境変数を設定し、uni-app公式サイトのグローバルファイルにテンプレートの記述がある
-
クロスドメインが必要なブラウザなので、vue.config.jsでクロスドメインの設定も必要です
-
ユニアプリ データ ストレージを使用する理由は、ユニアプリ データ ストレージの使用の原則はブラウザ ストレージであるためです。
-
ユニアプリのブラウザストレージはGoogle Chromeでは通常どおり使用できますが、ブラウザストレージはWeChat開発者ツールでは使用できず、互換性がありません
-
vue.config.js ファイルはグローバル変数を設定します - 公式 Web サイトのグローバル ファイルに例があります
chainWebpack: config => {
config
.plugin('define')
.tap(args => {
args[0]['process.env'].VUE_APP_BASE_API = '"/dev-api"'
return args
})
}
2.2 開発者ツールに対して WeChat を実行する場合
-
WeChat 開発者ツールおよび WeChat 環境であるため、クロスドメインはなく、vue.config.js ファイルは無効になり、プロキシは破棄されます。
-
WeChat環境がaxiosと互換性がないため、リクエストを送信できず、エラーが報告されます。以下の解決策があります。
-
WeChat 環境では、request.js ファイル内のベース アドレスをグローバル変数として書き込むことはできませんが、文字列 ip+port として書き込む必要があります。
正しい解決策
1. すべての axios を置き換え、 axios と同様のサードパーティ パッケージ@escook/request-miniprogramを使用します。
-
npm 公式 Web サイトにアクセスしてこのパッケージを検索すると、下にスクロールするとこのパッケージの詳細な使用方法が表示されます。
-
この方法は、axios の問題を解決できない場合にのみ使用されます。ここではお勧めしません。以下に axios の解決策があります。
基本コード - utils の下に requesthttp.js をビルドし、main.js に導入します (axios の使用と同様 - 詳細については「を参照」を参照)
// 按需导入 $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. サードパーティ パッケージの助けを借りて、WeChat 環境との互換性を保つために axios を使い続けます。
2.1 注意事項
-
この方法はブロガーが実際に試してみた結果、問題を解決できる方法なので、ぜひ順を追って読んでみてください。
-
uni-app や WeChat 開発者ツールにはバグがある場合があります。コンパイルを閉じて再度開くことを忘れないでください。
-
axios バージョンを制御せずに、axios に基づいて別のパッケージがダウンロードされる場合は、createError.js ファイルを axios パッケージに追加する必要があります。
2.2 具体的な実装
2.2.1 Hbuilder X での axios-miniprogram-adapter のダウンロード
npm i axios-miniprogram-adapter
2.2.2 プロジェクトnode_modelのaxiosパッケージの下にあるlib/core/ファイルパッケージを表示します。
2.2.3 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 ユニアプリから WeChat 開発者ツールを実行すると、Hbuilder X がエラーを報告します
2.2.5 エラー レポートは、axios-miniprogram-adapter が axios のパッケージを参照していることを意味します。Axios にはこのパッケージがないため、見つかりません。下のエラー レポートをクリックすると、対応するフォルダーで表示できます。
2.2.6 問題を解決するには、axios-miniprogram-adapter 用の createError.js パッケージを axios/lib/core に作成します
-
このディレクトリに移動して、createError.js ファイルを作成します
-
AxiosError.js ファイルの内容を createError.js ファイルに直接コピーします。
2.2.7 Hbuilder X の WeChat 開発者ツールでプロジェクトを再実行すると、エラーがなく、axios が使用でき、リクエストが送信されることがわかります。
2.2.8 request.js の完全なコード - 参照のみのため、コピーしないことをお勧めします
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
要約:
上記の操作により、axios はユニアプリとサテライト開発者ツールに対応することができ、ブラウザと WeChat 開発者ツールに出荷する際にベース アドレスの構成を切り替えるだけで、両端に対応できます。
このプロセスの後、axios を使用して WeChat 開発者ツールに実行リクエストを送信し、エラーを報告するアダプター「http」はビルドでは使用できませんが、実際の開発では使用できないというユニアプリについての予備的な深い印象もお持ちだと思います。状況は明らかに変わっているので、その原則を理解し、同じ原則を維持する必要があります。さあ、労働者を倒しましょう!
不備があればご指摘ください、ありがとうございます -- Fengguowuhen