回调函数未在 Action Creator 中正确执行
Callback functions not properly executing in Action Creator
我正在创建一个仪表板,它需要从 SQL 数据库的多个独立部分中提取元素,以便为应用程序创建一个可用的存储区。这些调用需要按顺序执行,因为它们依赖于前一次调用的数据作为后续调用的参数(例如:最初插入用户名和密码,这允许我们在数据库中找到一个用户 ID,我们可以然后用来定位他们可以看到的目标,然后我们可以用它来获取每个目标的实际数据)
我是 Redux 的新手(并且像这样将异步承诺链接在一起)。我一直认为实现这一点的最佳方法是将动作创建器中的不同承诺链接在一起。但是,我遇到了一些我无法完全解释的行为。
动作创作者如下:
export function setReduxStore(username, password) {
return function (dispatch) {
return dispatch(
loginUser(username, password)
).then((customerId) =>
setAvailableTargets(customerId)
)
}
}
如您所见,动作创建器首先触发 'loginUser()'。这部分正确触发。登录用户代码如下:
export function loginUser(username, password) {
return function (dispatch) {
return axios({
method: 'POST',
url: 'http://localhost:3050/users/login',
data: {
username: username,
password: password
}
}).then((response) => {
dispatch({type: "LOGIN_USER", payload: response})
return response.data.data[0].customer_id
})
}
}
但是,在 'setReduxStore()' 操作创建器中,我将其设置为触发第二个查询以帮助设置可用目标。此调用接受来自用户登录的 ID returned 作为参数。此操作的代码如下:
export function setAvailableTargets(customer_id) {
return function (dispatch) {
console.log("set targets fired with customer Id " + customer_id)
return axios({
method: 'GET',
url: 'http://localhost:3050/users/targets/' + customer_id,
data: {
customer_id: customer_id
}
}).then((response) => {
dispatch({type: 'SET_AVAILABLE_TARGETS', payload: response})
return response.data.data[0].id
})
}
}
你会注意到我在那个函数中有一个控制台日志语句——当我把它放在上面时
return function (dispatch)
它将使用 loginUser 提供的适当 ID 触发。但是,'return function (dispatch)' 下方的任何内容都没有触发。如果我在 promise 链之外调用该方法,它会起作用,所以它在触发函数但实际上不允许它执行任何有意义的代码片段的动作创建者中被调用的方式。
不确定它是否重要,但一旦弄清楚了这一点,我就需要进一步构建承诺链 - 并根据从 setAvailableTargets() returned 得到的 ID 获取实际数据。
编辑:对于有类似问题的任何人,下面的答案帮助我找到了一个看起来像这样的功能序列:
export function setReduxStore(username, password) {
return function (dispatch, getState) {
return dispatch(
loginUser(username, password)
).then(() => {
return dispatch (
setAvailableTargets(getState().currentUser.customerId)
)
})
}
}
我触发了一个函数,但它没有调度,这阻止了它 运行 任何有意义的代码。我必须确保 return 在捆绑函数的每个具体阶段进行新的调度。
继续上面的评论,您需要 return 操作中的普通对象。由于您使用的是 redux thunk 中间件,因此您可以 return 将函数作为操作。
export function setReduxStore(username, password) {
return function (dispatch) {
loginUser(username, password)
.then((customerId) =>
dispatch(setAvailableTargets(customerId))
)
}
}
export function loginUser(username, password) {
return function (dispatch) {
axios({
method: 'POST',
url: 'http://localhost:3050/users/login',
data: {
username: username,
password: password
}
}).then((response) => {
dispatch({type: "LOGIN_USER", payload: response})
//return response.data.data[0].customer_id
// Get data from store instead
})
}
}
export function setAvailableTargets(customer_id) {
return function (dispatch) {
console.log("set targets fired with customer Id " + customer_id)
axios({
method: 'GET',
url: 'http://localhost:3050/users/targets/' + customer_id,
data: {
customer_id: customer_id
}
}).then((response) => {
dispatch({type: 'SET_AVAILABLE_TARGETS', payload: response})
//return response.data.data[0].id
// Get data from store instead
})
}
}
redux 中异步操作的常见模式是定义 'request'、'success'、'failure' 操作类型,以便您的 UI 知道是否呈现加载动画、错误消息或响应数据。
我正在创建一个仪表板,它需要从 SQL 数据库的多个独立部分中提取元素,以便为应用程序创建一个可用的存储区。这些调用需要按顺序执行,因为它们依赖于前一次调用的数据作为后续调用的参数(例如:最初插入用户名和密码,这允许我们在数据库中找到一个用户 ID,我们可以然后用来定位他们可以看到的目标,然后我们可以用它来获取每个目标的实际数据)
我是 Redux 的新手(并且像这样将异步承诺链接在一起)。我一直认为实现这一点的最佳方法是将动作创建器中的不同承诺链接在一起。但是,我遇到了一些我无法完全解释的行为。
动作创作者如下:
export function setReduxStore(username, password) {
return function (dispatch) {
return dispatch(
loginUser(username, password)
).then((customerId) =>
setAvailableTargets(customerId)
)
}
}
如您所见,动作创建器首先触发 'loginUser()'。这部分正确触发。登录用户代码如下:
export function loginUser(username, password) {
return function (dispatch) {
return axios({
method: 'POST',
url: 'http://localhost:3050/users/login',
data: {
username: username,
password: password
}
}).then((response) => {
dispatch({type: "LOGIN_USER", payload: response})
return response.data.data[0].customer_id
})
}
}
但是,在 'setReduxStore()' 操作创建器中,我将其设置为触发第二个查询以帮助设置可用目标。此调用接受来自用户登录的 ID returned 作为参数。此操作的代码如下:
export function setAvailableTargets(customer_id) {
return function (dispatch) {
console.log("set targets fired with customer Id " + customer_id)
return axios({
method: 'GET',
url: 'http://localhost:3050/users/targets/' + customer_id,
data: {
customer_id: customer_id
}
}).then((response) => {
dispatch({type: 'SET_AVAILABLE_TARGETS', payload: response})
return response.data.data[0].id
})
}
}
你会注意到我在那个函数中有一个控制台日志语句——当我把它放在上面时
return function (dispatch)
它将使用 loginUser 提供的适当 ID 触发。但是,'return function (dispatch)' 下方的任何内容都没有触发。如果我在 promise 链之外调用该方法,它会起作用,所以它在触发函数但实际上不允许它执行任何有意义的代码片段的动作创建者中被调用的方式。
不确定它是否重要,但一旦弄清楚了这一点,我就需要进一步构建承诺链 - 并根据从 setAvailableTargets() returned 得到的 ID 获取实际数据。
编辑:对于有类似问题的任何人,下面的答案帮助我找到了一个看起来像这样的功能序列:
export function setReduxStore(username, password) {
return function (dispatch, getState) {
return dispatch(
loginUser(username, password)
).then(() => {
return dispatch (
setAvailableTargets(getState().currentUser.customerId)
)
})
}
}
我触发了一个函数,但它没有调度,这阻止了它 运行 任何有意义的代码。我必须确保 return 在捆绑函数的每个具体阶段进行新的调度。
继续上面的评论,您需要 return 操作中的普通对象。由于您使用的是 redux thunk 中间件,因此您可以 return 将函数作为操作。
export function setReduxStore(username, password) {
return function (dispatch) {
loginUser(username, password)
.then((customerId) =>
dispatch(setAvailableTargets(customerId))
)
}
}
export function loginUser(username, password) {
return function (dispatch) {
axios({
method: 'POST',
url: 'http://localhost:3050/users/login',
data: {
username: username,
password: password
}
}).then((response) => {
dispatch({type: "LOGIN_USER", payload: response})
//return response.data.data[0].customer_id
// Get data from store instead
})
}
}
export function setAvailableTargets(customer_id) {
return function (dispatch) {
console.log("set targets fired with customer Id " + customer_id)
axios({
method: 'GET',
url: 'http://localhost:3050/users/targets/' + customer_id,
data: {
customer_id: customer_id
}
}).then((response) => {
dispatch({type: 'SET_AVAILABLE_TARGETS', payload: response})
//return response.data.data[0].id
// Get data from store instead
})
}
}
redux 中异步操作的常见模式是定义 'request'、'success'、'failure' 操作类型,以便您的 UI 知道是否呈现加载动画、错误消息或响应数据。