当调用 API 的函数在 class 中定义时,如何通过 effect call 从 redux-saga 调用 API
How to call API from redux-saga by effect call when the function to call API is defined in class
我正在尝试通过 redux-saga 的效果调用来调用 API,但是什么时候开始调用 api 会抛出一个错误。 Cannot read property 'post' of null
真的很奇怪,因为我创建了一个简单的函数来测试我的通话是否正常
示例:
function requestGetUser() {
return axios.request({
method: 'get',
url: 'https://my-json-server.typicode.com/atothey/demo/user',
})
}
export function* fetchLoginSaga(action) {
const { data } = yield call(requestGetUser)
yield put(login({ id: data.id, name: data.firstName }))
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
上面这个例子有效
但是当我尝试从 class 内部调用 API 时,效果调用不起作用
// Depedencies
import axios from 'axios'
export default class BaseService {
/**
* Default http request instane
* @type { Axios.Instance }
*/
instance
/**
* Creates an instance of BaseService.
* @param { String } endpoint To manipulates the operations.
* @param { String } [baseUrl= ] The base url.
*/
constructor(endpoint, baseURL = process.env.BASE_URL) {
this.endpoint = endpoint
this.instance = axios.create({ baseURL })
this.instance.interceptors.response.use(this.responseInterceptor, this.handleResponseError)
}
/**
* Intercepts every response.
* @param { Object } response The response.
* @returns { Promise<Object> }
*/
responseInterceptor = response => response.data
/**
* Intercepts every error on response.
* @param { Object } error The respone error.
* @returns { Promise<Object> }
*/
handleResponseError = error => {
const {
response: {
data: { message },
},
} = error
return Promise.reject(new Error(message))
}
/**
* Make a post request with data.
* @param { Object } [data={}] The data to send as body.
* @param { Object } [requestParams={}] The params to make the request.
* @return { Promise<any> }
*/
post = (data, { url = this.endpoint, ...rest } = {}) => {
const response = this.instance.post(url, data, { ...rest })
return response
}
}
import BaseService from './baseService'
export class AuthService extends BaseService {
/**
* Initializes Auth Service.
*/
constructor() {
super('/auth/local')
}
/**
* Logs Current user.
* @param { String } identifier - User's Identifier
* @param { String } password - User´s password.
* @return { Promise<String> } jwt access token.
*/
async login(identifier, password) {
const user = await this.post({ password, identifier }, { url: '/auth/local' })// when I call return cant find post of null
return user
}
}
export default AuthService
import axios from 'axios'
import { call, takeLatest } from 'redux-saga/effects'
import { fetchLogin } from './authReducer'
import AuthService from 'api/authService'
const authService = new AuthService()
export function* fetchLoginSaga(action) {
const response = yield call(authService.login, 'email', 'password')
console.log({ response })// don't print
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
enter image description here
在幕后,redux-saga
将调用 your function with .apply
,缺少 authService
对象的 this
上下文,
存储库问题中的详细信息:
https://github.com/redux-saga/redux-saga/issues/27
您有 2 种方法可以解决这个问题:
- 将
call
签名更改为 yield call([auth, 'login'], "email", "password");
- 您可以改用
apply
效果 - yield apply(auth, auth.login, ["email", "password"]);
或者您可以使用 JavaScript:
将父对象绑定到 auth.login
函数
yield call(authService.login.bind(authService), 'email', 'password')
我建议改用正确的效果或效果签名!
“上下文”/“fn”的文档可以在 redux-saga
文档中找到:
https://redux-saga.js.org/docs/api/#callcontext-fn-args
我正在尝试通过 redux-saga 的效果调用来调用 API,但是什么时候开始调用 api 会抛出一个错误。 Cannot read property 'post' of null
真的很奇怪,因为我创建了一个简单的函数来测试我的通话是否正常 示例:
function requestGetUser() {
return axios.request({
method: 'get',
url: 'https://my-json-server.typicode.com/atothey/demo/user',
})
}
export function* fetchLoginSaga(action) {
const { data } = yield call(requestGetUser)
yield put(login({ id: data.id, name: data.firstName }))
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
上面这个例子有效
但是当我尝试从 class 内部调用 API 时,效果调用不起作用
// Depedencies
import axios from 'axios'
export default class BaseService {
/**
* Default http request instane
* @type { Axios.Instance }
*/
instance
/**
* Creates an instance of BaseService.
* @param { String } endpoint To manipulates the operations.
* @param { String } [baseUrl= ] The base url.
*/
constructor(endpoint, baseURL = process.env.BASE_URL) {
this.endpoint = endpoint
this.instance = axios.create({ baseURL })
this.instance.interceptors.response.use(this.responseInterceptor, this.handleResponseError)
}
/**
* Intercepts every response.
* @param { Object } response The response.
* @returns { Promise<Object> }
*/
responseInterceptor = response => response.data
/**
* Intercepts every error on response.
* @param { Object } error The respone error.
* @returns { Promise<Object> }
*/
handleResponseError = error => {
const {
response: {
data: { message },
},
} = error
return Promise.reject(new Error(message))
}
/**
* Make a post request with data.
* @param { Object } [data={}] The data to send as body.
* @param { Object } [requestParams={}] The params to make the request.
* @return { Promise<any> }
*/
post = (data, { url = this.endpoint, ...rest } = {}) => {
const response = this.instance.post(url, data, { ...rest })
return response
}
}
import BaseService from './baseService'
export class AuthService extends BaseService {
/**
* Initializes Auth Service.
*/
constructor() {
super('/auth/local')
}
/**
* Logs Current user.
* @param { String } identifier - User's Identifier
* @param { String } password - User´s password.
* @return { Promise<String> } jwt access token.
*/
async login(identifier, password) {
const user = await this.post({ password, identifier }, { url: '/auth/local' })// when I call return cant find post of null
return user
}
}
export default AuthService
import axios from 'axios'
import { call, takeLatest } from 'redux-saga/effects'
import { fetchLogin } from './authReducer'
import AuthService from 'api/authService'
const authService = new AuthService()
export function* fetchLoginSaga(action) {
const response = yield call(authService.login, 'email', 'password')
console.log({ response })// don't print
}
export function* watcherSaga() {
yield takeLatest(fetchLogin.type, fetchLoginSaga)
}
enter image description here
在幕后,redux-saga
将调用 your function with .apply
,缺少 authService
对象的 this
上下文,
存储库问题中的详细信息: https://github.com/redux-saga/redux-saga/issues/27
您有 2 种方法可以解决这个问题:
- 将
call
签名更改为yield call([auth, 'login'], "email", "password");
- 您可以改用
apply
效果 -yield apply(auth, auth.login, ["email", "password"]);
或者您可以使用 JavaScript:
将父对象绑定到auth.login
函数
yield call(authService.login.bind(authService), 'email', 'password')
我建议改用正确的效果或效果签名!
“上下文”/“fn”的文档可以在 redux-saga
文档中找到:
https://redux-saga.js.org/docs/api/#callcontext-fn-args