将递归函数转换为异步CPS实现(javascript) [英] Converting a recursive function into an asynchronous CPS implementation (javascript)

查看:171
本文介绍了将递归函数转换为异步CPS实现(javascript)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的功能。

  function duplicate_step_through_highlighted(element_jq,target_jq,char_cb){
console.log(element_jq);
var contents = element_jq.contents();
(var i = 0; i< contents.length; ++ i){
//如果文本节点,步
if(contents [i] .nodeType === 3 ){
//插入空文本节点
var new_tn = document.createTextNode('');
target_jq.append(new_tn);

//迭代它
var text = contents [i] .nodeValue;
for(var j = 0; j< text.length; j ++){
char_cb(text [j],new_tn);
new_tn.nodeValue + = text [j];
// ***我想要一个异步延迟这里***
}
} else {//类型应该是1:元素
// target_jq获取一个重复的元素插入,复制attrs
var new_elem = $(contents [i] .cloneNode(false))。appendTo(target_jq);
duplicate_step_through_highlighted($(contents [i]),$(new_elem),char_cb);

//然后对新创建的元素执行一个递归调用,如target_jq
//,而现有元素作为element_jq执行。 char_cb通过
}
}
}

正在做的是通过一次重建一个字符来重建HTML元素。有一个很好的理由这样做,我想要它的视觉效果输入。



所以现在没有任何延迟,所以我的元素立即重复。我检查结果是一致的,但是对我来说,我可能需要完全重写功能,以便在插入每个字符后才能够进入异步延迟。



我需要重新编写它,并有一个堆栈来跟踪我在元素中的位置吗?

解决方案

你可能想看看我最近的一个 answer 这个较旧的 Demo ),关于如何实现这种效果。






提示:不要将元素复制成新的元素,只需隐藏它们并使其显示为零件。



此外,它可能是除了原生DOM元素,更容易处理jQuery实例。所以是的,重写可能会做:-)而且我认为它也需要一个堆栈。

  function animate(elements,回调){
/ * get:要隐藏的元素要显示的数组,回调函数* /
var i = 0;
(function iterate(){
if(i< elements.length){
elements [i] .style.display =block; // show
animateNode元素[i],迭代);
i ++;
} else if(callback)
callback();
})();
function animateNode(element,callback){
var pieces = [];
if(element.nodeType == 1){
while(element.hasChildNodes())
pieces.push(element.removeChild(element.firstChild));
setTimeout(function childStep(){
if(pieces.length){
animateNode(pieces [0],childStep);
element.appendChild(pieces.shift()) ;
} else
callback();
},1000/60);
} else if(element.nodeType == 3){
pieces = element.data.match(/。{0,2} / g); // 2:每帧的字符数
element.data =;
(function addText(){
element.data + = pieces.shift();
setTimeout(pieces.length
?addText
:callback,
1000/60);
})();
}
}
}

animate($(#foo)。children());

演示在jsfiddle.net



如何工作:




  • addText 函数向当前文本节点添加一些字符,并设置自己的超时 - 动画!如果一切都完成,它将调用回调函数。

  • childStep 在一个子节点上运行动画,并将其自身作为回调,直到没有孩子被留下 - 然后nvokes 回调函数。

  • 一起, animateNode 递归运行在节点树上,按照顺序动画文本节点。

  • iterate 通过将自身作为回调函数调用所有输入元素的函数调用 animateNode (在解除它们之后)。所有输入元素完成后,它将调用外部回调,作为第二个参数给出 animate


Here's my function.

    function duplicate_step_through_highlighted (element_jq, target_jq, char_cb) {
        console.log( element_jq);
        var contents = element_jq.contents();
        for (var i = 0 ; i < contents.length; ++i) {
            // if text node, step
            if (contents[i].nodeType === 3) {
                // insert empty text node
                var new_tn = document.createTextNode('');
                target_jq.append(new_tn);

                // iterate it 
                var text = contents[i].nodeValue;
                for (var j = 0; j < text.length; j++) {
                    char_cb(text[j],new_tn);
                    new_tn.nodeValue += text[j];
                    // *** I want an async delay here *** 
                }
            } else { // type should be 1: element
                // target_jq gets a duplicate element inserted, copying attrs
                var new_elem = $(contents[i].cloneNode(false)).appendTo(target_jq);
                duplicate_step_through_highlighted($(contents[i]),$(new_elem),char_cb);

                // then a recursive call is performed on the newly created element as target_jq
                // and the existing one as element_jq. char_cb is passed in
            }
        }
    }

What I'm doing is rebuilding an HTML element by reconstructing it one character at a time. There is a good reason for doing this, I want the visual effect of it getting "typed in".

So right now there are no delays so my element gets duplicated instantly. I have checked that the result is consistent, but it is becoming clear to me that I will probably need to completely re-write the functionality in order for me to be able to put in an asynchronous delay after each character is inserted.

Will I need to re-write it and have a stack to keep track of my position within the elements?

解决方案

You might want to have a look at my recent answer or this older one (Demo), on how to implement such an effect.


Tip: Don't clone the elements into new ones, just hide them and make them appear part-for-part.

Also, it might be easier not to deal with jQuery instances at all but native DOM elements. So yes, a rewrite might do :-) And I think it does need a stack as well.

function animate(elements, callback) {
/* get: array with hidden elements to be displayes, callback function */
    var i = 0;
    (function iterate() {
        if (i < elements.length) {
            elements[i].style.display = "block"; // show
            animateNode(elements[i], iterate); 
            i++;
        } else if (callback)
            callback();
    })();
    function animateNode(element, callback) {
        var pieces = [];
        if (element.nodeType==1) {
            while (element.hasChildNodes())
                pieces.push(element.removeChild(element.firstChild));
            setTimeout(function childStep() {
                if (pieces.length) {
                    animateNode(pieces[0], childStep); 
                    element.appendChild(pieces.shift());
                } else
                    callback();
            }, 1000/60);
        } else if (element.nodeType==3) {
            pieces = element.data.match(/.{0,2}/g); // 2: Number of chars per frame
            element.data = "";
            (function addText(){
                element.data += pieces.shift();
                setTimeout(pieces.length
                    ? addText
                    : callback,
                  1000/60);
            })();
        }
    }
}

animate($("#foo").children());

Demo at jsfiddle.net

How it works:

  • The addText function adds some character to the current text node, and sets a timeout for itself - animation! In case everything is done, it invokes the callback function.
  • childStep runs the animation on a childnode, and passes itself as the callback until no children are left - then nvokes the callback function.
  • Both together, animateNode recursively runs over the node tree and animates the textnodes in thier order.
  • the iterate function calls animateNode (after unhinding them) on all input elements, by passing itself as the callback. After all input elements are finished, it invokes the outer callback which is given as the second argument to animate.

这篇关于将递归函数转换为异步CPS实现(javascript)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆