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



我正在尝试使用WebAssembly将我用自己的编程语言编写的一个程序移植到web。然而,我遇到了一个问题。也就是说,我的一个程序应该打印用户输入的数字的所有数字排列。你可以看到实时版本
问题是,当您输入一些位数相对较多的数字时,例如"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工作程序中运行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');

最新更新