首页>文档>Rouse开发文档>过滤器异步解决方案

需要支持?

如果通过文档没办法解决您的问题,请提交工单获取我们的支持!

过滤器异步解决方案

分别对两种钩子做异步讨论:

  • Action
    对于动作而言,它只是在正常工作流中被同步触发的行为,并不会对原工作流产生影响。因此异步情况【不考虑】。
  • Filter
    对于过滤器而言,它需要返回数据后正常工作流才能根据返回的数据继续工作,如果它出现异步,工作流也需要等待它完成后才能继续执行。因此它的异步情况【应该被考虑】。

普通数据过滤

正常运行的工作流中执行了一个名为”sample_filter”的过滤器,被过滤的参数是“filterMe”字符串,以及其他两个辅助参数:

var result = apply_filters("sample_filter","filterMe","otherArg1","otherArg2");
console.log(result);
//...后续其他操作

在未添加”sample_filter”过滤器前,运行结果屏幕显示字符串:filterMe

现在添加一个过滤器,目的是将被过滤的字符串和其他两个参数使用~符号串接起来:

//过滤器
function sample_filter_connect_strings( original_string, arg1, arg2 ) {
    return original_string+"~"+arg1+"~"+arg2;
}
add_filter("sample_filter", sample_filter_connect_strings);
//正常工作流
var result = apply_filters("sample_filter","filterMe","otherArg1","otherArg2");
console.log(result);
//...后续其他操作

此时,运行结果屏幕显示过滤后的字符串:filterMe~otherArg1~otherArg2

异步过滤解决方案

同样是上面的例子,如果过滤的字符串是来自后端服务器或需要一定时间后才能返回,那么怎么办呢?假设现在过滤器本身需要延迟1秒后才返回结果,我们首先会想到的是:

//过滤器
function sample_filter_connect_strings( original_string, arg1, arg2 ) {
    setTimeout(function(){
        return original_string+"~"+arg1+"~"+arg2;
    },1000)
}
add_filter("sample_filter", sample_filter_connect_strings);
//正常工作流
var result = apply_filters("sample_filter","filterMe","otherArg1","otherArg2");
console.log(result);
//...后续其他操作

我们逻辑上认为延迟后返回数据即可。然而事实上屏幕却显示:undefined
原因是等待时间造成了异步行为,浏览器并不会停在那里不动。也就是说,在1s延时的时候,浏览器仍然在继续执行代码。由于过滤器并没有return,因此得到的结果是undefined

这种行为新手很容易犯错:这类似于发起的Ajax请求,浏览器会在某个时间后才会得到结果,然而后面的代码段并不会暂停等待。通常这种情况我们的处理方式是callback回调。

提供一个我个人提出的解决方案

我们这样理解:原始的工作流“被过滤的数据”是一个function,这个function本身接受一个回调参数。在数据处理完成后,将数据回调给参数继续后续处理。因此我们将工作流改造为下面的样子来进行后续处理:

var tobe_Filtered = function(resolve) {
    resolve( "filterMe" );
}
var callback = function(result) {
    console.log(result);
    //...后续其他操作
}
var result_function = apply_filters("sample_filter",tobe_Filtered,"otherArg1","otherArg2");
result_function(callback)

运行上述代码时,第8行先尝试过滤 tobe_Filtered 方法,发现未添加过滤器,因此得到的结果仍然是 tobe_Filtered。第9行执行了result_function(tobe_Filtered)方法。执行时,调用了第2行的 resolve,而 resolve 又是在第9行传入的callback,因此,callback 接收到了第 1行返回的“filterMe”数据。

简化一下会更好看:

apply_filters("sample_filter",function( resolve ){
    resolve( "filterMe" );
},"otherArg1","otherArg2")(function( result ){
    console.log(result);
    //...后续其他操作
})

根据“过滤后的数据和过滤前的数据类型原则上相同”这个条件,因此过滤器也应该返回的是function。
由于上一步返回的是方法,要得到数据需要等待上一步回调,因此需要编写上一步的回调函数。

//过滤器
function sample_filter_connect_strings( tobe_Filtered_function, arg1, arg2 ) {
    return function( resolve ) {
        //从被过滤的方法中回调数据
        tobe_Filtered_function(function( data_tobe_filtered ){
            //异步回调数据
            setTimeout(function(){
                resolve( data_tobe_filtered+"~"+arg1+"~"+arg2 );
            },1000)
        })
    }
}
add_filter("sample_filter", sample_filter_connect_strings);
//正常工作流
apply_filters("sample_filter",function( resolve ){
    resolve( "filterMe" );
},"otherArg1","otherArg2")(function( result ){
    console.log( result );
    //...后续其他操作
})

于是,就实现了异步过滤的效果。

如果只是为了得到新数据,而不是从上一步的结果中过滤,也可以忽略被过滤的方法,直接resolve新数据:

//过滤器
function sample_filter_connect_strings( tobe_Filtered_function, arg1, arg2 ) {
    return function( resolve ) {
        //直接异步resolve新数据,而不从上一步的回调方法中得到数据
        setTimeout(function(){
            resolve( "New Data" );
        },1000)
    }
}
add_filter("sample_filter", sample_filter_connect_strings);
//正常工作流
apply_filters("sample_filter",function( resolve ){
    resolve( "filterMe" );
},"otherArg1","otherArg2")(function( result ){
    console.log( result );
    //...后续其他操作
})

总结

异步过滤解决方案过滤的并不是数据,而是方法。该方法接受一个回调函数,将数据回调给函数后进行后续处理。
由于上一步返回的是方法,要得到数据需要等待上一步回调,因此需要编写上一步的回调函数。
使用Promise也可实现类似功能

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索