C++ std::flush 的 JavaScript 等价物是什么?

What is the JavaScript equivalent of C++ std::flush?

我正在尝试使用 WebAssembly 将我用自己的编程语言编写的程序之一移植到网络上。但是,我 运行 遇到了问题。也就是说,我的一个程序应该打印用户输入的数字的所有排列。你可以看到 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, 0, 0, 0,
         0, 0, 0, 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 Worker 中的 Web 程序集。

您的 HTML 文件将创建一个工人。在 worker 内部,您需要 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');