将递归函数转换为异步

将递归函数转换为异步

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

问题描述

这是我的功能.

    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
            }
        }
    }

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

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?

推荐答案

你可能想看看我最近的答案这个较旧的 (Demo),关于如何实现这样的效果.

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.

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

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());

jsfiddle.net 上的演示

工作原理:

  • addText 函数向当前文本节点添加一些字符,并为自身设置超时 - 动画!如果一切都完成了,它会调用 callback 函数.
  • childStep 在子节点上运行动画,并将自身作为回调传递,直到没有子节点剩下 - 然后调用 callback 函数.
  • 两者一起,animateNode 递归地遍历节点树并按顺序为文本节点设置动画.
  • iterate 函数通过将自身作为回调传递给所有输入元素调用 animateNode(在取消隐藏它们之后).在所有输入元素完成后,它调用外部 callback,它作为 animate 的第二个参数给出.
  • 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)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 10:34