如何编写可复用的通用Promise then/catch处理器并传递上下文参数
复用Axios响应/错误处理器的ES6原生方案
你遇到的这种重复编写闭包的问题很常见,从Python的柯里化思路出发完全没问题,JS里有几种原生的方式可以优雅解决这个问题,不需要引入任何额外依赖:
方法1:箭头函数实现柯里化(最直观的方案)
我们可以写一个"处理器生成函数",先传入Vue组件实例(也就是你之前的myVue),返回一个真正接收response或error的处理器函数:
// 定义可复用的处理器生成器 const createResponseHandler = (vueInstance) => (response) => { // 这里可以根据response的实际内容生成消息,示例简化为固定值 vueInstance.$root.$emit(base_messages.EV_USER_MESSAGE, "success"); }; const createErrorHandler = (vueInstance) => (error) => { // 同理,错误时可以从error里提取具体消息,这里简化为"failure" vueInstance.$root.$emit(base_messages.EV_USER_MESSAGE, "failure"); };
使用的时候直接传入当前组件的this即可:
axios.post(this.action_url, qs.stringify(data), config) .then(createResponseHandler(this)) .catch(createErrorHandler(this)); // 其他请求直接复用,完全不用重复写闭包 axios.post(another_url, qs.stringify(data2), config2) .then(createResponseHandler(this)) .catch(createErrorHandler(this));
这种方式完全符合你想要的"预绑定上下文"的思路,箭头函数的写法也很简洁,ES6完全支持。
方法2:使用Function.prototype.bind()绑定上下文
如果你更习惯写普通函数,也可以用原生的bind方法把Vue实例绑定到处理器的this上:
// 定义基础处理器函数 function handleResponse(response) { // 这里的this就是我们绑定的Vue组件实例 this.$root.$emit(base_messages.EV_USER_MESSAGE, "success"); } function handleError(error) { this.$root.$emit(base_messages.EV_USER_MESSAGE, "failure"); }
使用时通过bind绑定当前上下文:
axios.post(this.action_url, qs.stringify(data), config) .then(handleResponse.bind(this)) .catch(handleError.bind(this));
bind会创建一个新函数,把你传入的this绑定到原函数的执行上下文中,这样处理器就能访问到Vue实例的方法了。
扩展:更灵活的通用处理器
如果你的逻辑允许,还可以把消息类型也作为参数预绑定,进一步简化:
const createMessageHandler = (vueInstance, messageType) => (payload) => { // 这里可以根据payload是response还是error做不同处理 vueInstance.$root.$emit(base_messages.EV_USER_MESSAGE, messageType); };
使用时:
axios.post(this.action_url, qs.stringify(data), config) .then(createMessageHandler(this, "success")) .catch(createMessageHandler(this, "failure"));
这两种方案都是ES6原生支持的,完全满足你复用处理器同时保留上下文的需求,选哪种取决于你的代码风格偏好——箭头函数柯里化更直观,bind则适合已有普通函数的场景。
内容的提问来源于stack exchange,提问作者JL Peyret
相关产品推荐
相关产品推荐

