观察中间件中的存储状态更改

时间:2015-10-20 16:13:14

标签: redux

我正在编写一段Redux中间件,负责将用户的OAuth AccessToken添加到API_CALL个阳台,然后再点击redux-api-middleware

// sign appends the `Authorization` HTTP Header to an API_CALL action
function sign(action) {
    action[CALL_API].headers = {
        ...action[CALL_API].headers,
        Authorization: `Bearer ${getState()auth.accessToken}`;
    }
}

// Redux middleware signature.
return ({dispatch, getState}) => {
    return next => action => {
        if (action[CALL_API]) {
            sign(action);
        }
        return next(action);
    }
}

但是,我也希望这个中间件检测用户的AccesToken何时过期...

function tokenExpired() {
    return (Date.now() > getState().auth.expirationTime);
}

当发生这种情况时,中间件会保留该操作(阻止它被传递到链中的next中间件)并将其存储在内部列表中。然后开始异步。令牌刷新过程通过调度'刷新访问令牌'FSA:

if (tokenExpired()) {
    // detainActions is an array, declared outside 
    // of the middleware's scope.
    detainActions.push(action);
    dispatch(refreshAccessToken());
}
else {
    next(sign(action));
}

最后,我想监听“刷新访问令牌”流程何时完成并刷新(重新发送)所有被扣留的操作。目前,我正在通过查看AUTHENTICATION_RESPONSE FSA在我的中间件流动时这样做(AUTHENTICATION_RESPONSE操作被调度为refreshAccessToken thunk的副作用。

// Redux middleware signature.
return ({dispatch, getState}) => {
    return next => action => {

        if (action.type === AUTHENTICATION_RESPONSE && !action.error) {
            // Let the AuthResponse action pass to the store.
            next(action);

            // Flush detained actions now we have a new grant.
            return flushAndRedispatchDetainedActions(dispatch);
        }
        else {
            // Sign CALL_API requests logic as above.
        }
    }
}

但是我对这种方法不满意,因为不确定AUTHENTICATION_RESPONSE FSA实际上会击中减速器(它可能会被其他中间件截获,或者被进一步推迟)。

我考虑过的可能的替代方法是让refreshAccessToken actionCreator返回一个返回Promise的thunk;这样我的中间件可以在刷新和重放所有请求之前等待该承诺解决,即:

if (tokenExpired()) {
    // refreshAccessToken thunk returns a Promise. 
    dispatch(refreshAccessToken());
        .then(flushAndRedispatchDetainedActions();
}

或者替代方案我可以让我的中间件直接观察商店并在auth.accessToken值更改时触发操作 - 但是,我不清楚中间件观察商店的指导是什么(我猜因为在创建最终商店对象之前需要实例化中间件,所以这是不可能的。)

谢谢:)

更新

在回家的路上思考问题;如果我要将实际的身份验证逻辑从refreshAccessToken(一个thunk'd动作创建者)移出,并进入中间件本身,那么我会节省很多痛苦:

// Redux middleware signature.
return ({dispatch, getState}) => {
    return next => action => {
        if (action[CALL_AUTH]) {
            authHelper.refreshGrant()
                .then(grant => dispatch(processGrant(newGrant));
        }
        else {
            // Sign CALL_API requests logic as above.
        }
    }
}

0 个答案:

没有答案