C ++ std :: flush的JavaScript等效项是什么? index.html worker.js

问题描述

我正在尝试使用WebAssembly将以我自己的编程语言编写的程序之一移植到Web上。但是,我遇到了一个问题。即,我的程序之一应该打印用户输入的数字的所有数字排列。您可以看到live version
问题是,当您输入一些具有较大数字的数字(例如“ 1234567”)时,即使程序几乎立即开始查找排列并将其立即打印到innerHTML中,浏览器也不会在以下位置显示任何排列全部找到它们。这不是所需的行为,所需的行为是在找到排列后立即打印该排列。我怎样才能做到这一点?我用于打印字符串的代码在这里

function printString(ptr) {
    let buffer=new Uint8Array(memory.buffer);
    let str="";
    while (buffer[ptr]) {
        str+=String.fromCharCode(buffer[ptr]);
        ptr++;
    }
    document.getElementById("format_as_code").innerHTML+=str;
}

这是我用来查找排列的代码

/*
 * This will be a test to see whether calling JavaScript functions from AEC
 * works as expected. It will also attempt to expose as many potential compiler
 * bugs as possible by implementing the permutations algorithm.
 */

//So,those are JavaScript functions which I am planning to call from AEC:
Function printInt(Integer32 int) Which Returns nothing Is External;
Function printString(CharacterPointer ptr) Which Returns nothing Is External;
Function clearScreen() Which Returns nothing Is External;

//JavaScript equivalent of C "strlen" is the "length" property of a string
// and there is,as far as I kNow,no way to call it from outside of JS.
//Nevertheless,I think I can easily write it myself.
Function strlen(CharacterPointer ptr) Which Returns Integer32 Does
    Return ValueAt(ptr) = 0 ?
                                0
                            :
                                1 + strlen(ptr + 1);
EndFunction

Integer32 originalNumberOfDigits[10];
Integer32 NDEBUG := 1;
Integer32 numberOfPermutations;

Function recursiveProcedure(CharacterPointer currentAttempt)
    Which Returns nothing Does
    Integer32 lengthOfTheCurrentAttempt := strlen(currentAttempt);
    If not(NDEBUG) Then
        printString(
            "DEBUG: \"recursiveProcedure\" has been invoked with the argument: \""
            );
        printString(currentAttempt);
        printString("\". \"strlen\" says it has length of ");
        printInt(lengthOfTheCurrentAttempt);
        printString(".\n");
    EndIf
    Integer32 currentNumberOfDigits[10] :=
        {0,0};
    Integer32 i := 0;
    While i<lengthOfTheCurrentAttempt Loop
        currentNumberOfDigits[ValueAt(currentAttempt + i) - '0'] :=
            currentNumberOfDigits[ValueAt(currentAttempt + i) - '0'] + 1;
        i := i + 1;
    EndWhile
    If not(NDEBUG) Then
        i := 0;
        While i < 10 Loop
            printString("DEBUG: The current number has ");
            printInt(currentNumberOfDigits[i]);
            printString(" digits '");
            printInt(i);
            printString("'.\n");
            i := i + 1;
        EndWhile
    EndIf
    i := 0;
    While i < 10 Loop
        If currentNumberOfDigits[i] > originalNumberOfDigits[i] Then
            If not(NDEBUG) Then
                printString("DEBUG: There are too many digits '");
                printInt(i);
                printString("',ending \"recursiveProcedure\".\n");
            EndIf
            Return;
        EndIf
        i := i + 1;
    EndWhile
    Integer32 haveWeFoundAPermutation := 1;
    i := 0;
    While i < 10 Loop
        If currentNumberOfDigits[i] < originalNumberOfDigits[i] Then
            haveWeFoundAPermutation := 0;
        EndIf
        i := i + 1;
    EndWhile
    If haveWeFoundAPermutation Then
        printString("Permutation #");
        numberOfPermutations:=numberOfPermutations+1;
        printInt(numberOfPermutations);
        printString(": ");
        printString(currentAttempt);
        printString("\n");
        Return;
    EndIf
    Character digitWeAreAdding := '0';
    While digitWeAreAdding < '9' + 1 Loop //The less-than-or-equal operator
                                          //">=" hasn't yet been implemented.
        Character newAttempt[12];
        i := 0;
        While i < 12 Loop
            If i < lengthOfTheCurrentAttempt Then
                newAttempt[i] := ValueAt(currentAttempt + i);
            Else
                newAttempt[i] := 0;
            EndIf
            i := i + 1;
        EndWhile
        newAttempt[lengthOfTheCurrentAttempt] := digitWeAreAdding;
        If currentNumberOfDigits[digitWeAreAdding - '0'] < 
            originalNumberOfDigits[digitWeAreAdding - '0'] Then //To speed
                                                                //things up
                                                                //a bit.
            recursiveProcedure(AddressOf(newAttempt[0]));
        EndIf
        digitWeAreAdding := digitWeAreAdding + 1;
    EndWhile
EndFunction

Function printPermutationsOfDigits(Integer32 original)
    Which Returns nothing Does
    clearScreen();
    If original < 0 Then
        original := -original;
    EndIf
    printString("Printing all the permutations of digits of the number: ");
    printInt(original); //Unfortunately,the JavaScript standard library
                        //doesn't have "printf".
    printString("\n");
    Integer32 i := 0;
    While i < 10 Loop
        originalNumberOfDigits[i] :=     0;
        i                         := i + 1;
    EndWhile
    If original = 0 Then
        originalNumberOfDigits[0] := 1;
    EndIf
    While original > 0 Loop
        originalNumberOfDigits[mod(original,10)] :=
            originalNumberOfDigits[mod(original,10)] + 1;
        original := original / 10;
    EndWhile
    If not(NDEBUG) Then
        i := 0;
        While i < 10 Loop
            printString("DEBUG: The original number has ");
            printInt(originalNumberOfDigits[i]);
            printString(" digits '");
            printInt(i);
            printString("'.\n");
            i := i + 1;
        EndWhile
    EndIf
    numberOfPermutations := 0;
    recursiveProcedure("");
    printString("The end!");
EndFunction

解决方法

您遇到的问题是代码永远不会给浏览器任何时间来更新UI。正如其他人指出的那样,如果您在代码中使用了setTimeout,则可以给浏览器一些喘息的空间。但这仅在超时发生在recursiveProcedure内部并用于调用recursiveProcedure的下一次迭代的情况下才有效。这似乎并不容易或可行。但是还有另一种解决方案:

在网络工作者中运行Web程序集。

您的HTML文件将创建一个工作程序。在工作人员内部,您需要提供was文件并拥有printStringprintString将回调该页面以更新输出。像这样:

index.html

<script>
var myWorker = new Worker('worker.js');
// When we get a message from the worker,update the format_as_code element with the data sent
myWorker.onmessage = function(e) {
    document.getElementById("format_as_code").innerHTML += e.data;
}
</script>

worker.js

function printString(ptr) {
    let buffer=new Uint8Array(memory.buffer);
    let str="";
    while (buffer[ptr]) {
        str+=String.fromCharCode(buffer[ptr]);
        ptr++;
    }
    // We post back to the page the contents of the string
    postMessage(str);
}
// This is the file that contains your wasm compilation result
importScripts('wasm_compiled.js');