简体   繁体   中英

My code is not executed the same locally and in codepen or plunker

I have code like this using jQuery Terminal:

function show() {
    for (var i = 0; i < 100; ++i) {
        this.echo('line ' + i, {
            flush: false
        });
    }
    this.flush();
    setTimeout(function() {
        //this.flush();
    }, 0);
}

var term = $('body').terminal({
    show: show
}, {
    onBlur: function() {
        return false;
    },
    onInit: function(term) {
        show.apply(term);
    }
});

and inside this codepen the the lines are not show up until I resize horizontally the browser window. It work when I put flush in setTimeout 0:

setTimeout(function() {
    term.flush();
}, 0);

It work normally when I run the same code (without setTimeout) in local server. I've also tried to embed the code in iframe and It also run as expected. And other thing when I execute command show (type show and press enter) the executed command and prompt is add at the end (after the lines added by echo) but when I resize the window they are in placed before the lines as they should.

Anybody have a clue why this is happening? Why is the code executed differently locally and in codepen?

I've trid to setup breakpoints in jquery.terminal-src.js file but didn't figure out why flush don't make lines show up. When I step throught the code it seems that output_buffer array is empty when flush is called but somehow the lines show up when I resize the window and resize method is executed.

I believe this is because the echo function is asynchronous. It uses Deferred internally and is documented as

// :: it use $.when so you can echo a promise
// -------------------------------------------------------------
echo: function(string, options) {

In race conditions due to the Codepen overhead (generated code executed by codepen : note the window.CP lines added automatically)

for (var i = 0; i < 100; ++i) {
    if (window.CP.shouldStopExecution(1)) {
        break;
    }
    this.echo('line ' + i, { flush: false });
}
this.flush();
setTimeout(function () {
}, 0);
window.CP.exitedLoop(1);

Then it happens that the resolve of the JQuery Deferred of the echo which is performed "immediately" but yet asynchronously is fired after calling the flush . Thus the flush flushes nothing at that time.

Setting a setTimeout queues the flush such that it happens after the echo .

In my opinion, if they use deferred for the echo (or any method), they should align all the methods to do so. And therefore the flush should also use deferred which would then be queued and would resolve in order.

Resizing the window is just forcing a flush afterwards, this is why it displays then.

By the way, the object creation also seems to be deferred. Thus, if you use the variable term in the show method (not in the setTimeout) you will notice that it is not yet initialized and causes an error. This means that the show function is called before the variable assignment. Which is another cause for asynchronous confusion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM