Hi all,
I've this code in my library (at bottom of post), the entry point here is the MinifyAllFilesOnFolderAsync sub,
the sub should recursively minimize all JS and CSS files in the specified folder SourceDir and save them in DestDir
mantaing the folder structure.
I call it from Main this way:
The MinifyAllFilesOnFolderAsync sub is called, then inside it, the sub MinifyAllFilesOnFolderInternalAsync is called,
a Wait For wait for all files are processed recursively and then the result return should return back to the calling sub (a Wait For in the Main)
It is called with:
At this point all files are listed in the SourceDir folder, it process some files and recursively search files inside subfolfers and process them if they are JS or CSS, but then at some time the execution flow is not what I expect.
The sub MinifyAllFilesOnFolderInternalAsync call itself recursively if folder is found, but it should only terminate one time and call back the MinifyAllFilesOnFolderAsync to process it's return and then return it back to the Main with CallSubDelayed3 .
Some files are processed, but I never see the COMPLETED log, the sub never return back to calling sub.
Note that MinifyFileToFileAsync called to process a file when found, is also asyncronous sub, and it works well if called from the main.
In the MinifyAllFilesOnFolderInternalAsync I even use File.ListFilesAsync instead of File.ListFiles.
I followed it for 4 hours line by line in debug mode, but no luck.
The For Each f As String In Files should only terminate one time and here the sub should return back the non-Null value, that is a MinifiedFolderItem Type.
Instead it is called more times, even if the sub itself do not return back but continue it's execution, but at the end do not fires the event on the calling sub.
Please someone know what is wrong here ?
Many thanks.
I've this code in my library (at bottom of post), the entry point here is the MinifyAllFilesOnFolderAsync sub,
the sub should recursively minimize all JS and CSS files in the specified folder SourceDir and save them in DestDir
mantaing the folder structure.
I call it from Main this way:
B4X:
Dim Compressor As YUICompressor
Compressor.Initialize(Me, "Compressor")
Compressor.MinifyAllFilesOnFolderAsync (File.DirTemp, File.DirApp, True)
Wait For Compressor_FolderComplete (Success As Boolean, Item As MinifiedFolderItem)
The MinifyAllFilesOnFolderAsync sub is called, then inside it, the sub MinifyAllFilesOnFolderInternalAsync is called,
a Wait For wait for all files are processed recursively and then the result return should return back to the calling sub (a Wait For in the Main)
It is called with:
B4X:
MinifyAllFilesOnFolderInternalAsync (SourceDir, DestDir, UseMinPrefix)
Wait For Compressor_FolderComplete (Success As Boolean, FolderItem As MinifiedFolderItem)
At this point all files are listed in the SourceDir folder, it process some files and recursively search files inside subfolfers and process them if they are JS or CSS, but then at some time the execution flow is not what I expect.
The sub MinifyAllFilesOnFolderInternalAsync call itself recursively if folder is found, but it should only terminate one time and call back the MinifyAllFilesOnFolderAsync to process it's return and then return it back to the Main with CallSubDelayed3 .
Some files are processed, but I never see the COMPLETED log, the sub never return back to calling sub.
Note that MinifyFileToFileAsync called to process a file when found, is also asyncronous sub, and it works well if called from the main.
In the MinifyAllFilesOnFolderInternalAsync I even use File.ListFilesAsync instead of File.ListFiles.
I followed it for 4 hours line by line in debug mode, but no luck.
The For Each f As String In Files should only terminate one time and here the sub should return back the non-Null value, that is a MinifiedFolderItem Type.
Instead it is called more times, even if the sub itself do not return back but continue it's execution, but at the end do not fires the event on the calling sub.
Please someone know what is wrong here ?
Many thanks.
B4X:
#Event: FolderComplete (Success As Boolean, Item As MinifiedFolderItem)
Type MinifiedFolderItem (SourceDir As String, DestDir As String, OriginalSize As Int, MinifiedSize As Int, Compression As Float)
Public Sub MinifyAllFilesOnFolderAsync (SourceDir As String, DestDir As String, UseMinPrefix As Boolean) As ResumableSub
mFolderFilesOriginalSize = 0
mFolderFilesMinifiedSize = 0
''' Wait For (MinifyAllFilesOnFolderInternalAsync (SourceDir, DestDir, UseMinPrefix)) Complete (FolderItem As MinifiedFolderItem)
MinifyAllFilesOnFolderInternalAsync (SourceDir, DestDir, UseMinPrefix)
Wait For Compressor_FolderComplete (Success As Boolean, FolderItem As MinifiedFolderItem)
Log("======================== COMPLETED ========================")
If Success Then
FolderItem.SourceDir = SourceDir
FolderItem.DestDir = DestDir
FolderItem.OriginalSize = mFolderFilesOriginalSize
FolderItem.MinifiedSize = mFolderFilesMinifiedSize
FolderItem.Compression = MapFloat(mFolderFilesMinifiedSize, 0, mFolderFilesOriginalSize, 100, 0)
If SubExists(mModule, mEventName & "_FolderComplete") Then
CallSubDelayed3(mModule, mEventName & "_FolderComplete", True, FolderItem)
End If
Else
If SubExists(mModule, mEventName & "_FolderComplete") Then
CallSubDelayed3(mModule, mEventName & "_FolderComplete", False, Null)
End If
End If
Return True
End Sub
Private Sub MinifyAllFilesOnFolderInternalAsync (SourceDir As String, DestDir As String, UseMinPrefix As Boolean) As ResumableSub
' Add error handling for file existence check
If File.Exists(SourceDir, "") = False Or File.IsDirectory(SourceDir, "") = False Then
Log("The SourceDir folder does not exist: " & SourceDir)
CallSubDelayed3(Me, mEventName & "_FolderComplete", False, Null)
Return True ' Ensure proper termination
End If
If DestDir = "" Then DestDir = SourceDir
Log(" ")
Log("CURRENT SOURCE FOLDER: " & SourceDir)
Log(" CURRENT DEST FOLDER: " & DestDir)
Log(" ")
' Dim Files As List = File.ListFiles(SourceDir)
' Handle asynchronous file listing
Wait For (File.ListFilesAsync(SourceDir)) Complete (Success As Boolean, Files As List)
If Success Then
For Each f As String In Files
If File.IsDirectory(SourceDir, f) = False Then
Log("FOUND FILE: " & File.Combine(SourceDir, f))
Dim fName As String
' Touch .js and .css files only, ignore all other extentions
If f.EndsWith(".js") Then
If UseMinPrefix Then
If f.ToLowerCase.Contains(".min") = False Then
fName = f.SubString2(0, f.IndexOf(".js")) & ".min.js"
Else
Log("JS File already minified. Skip it: " & File.Combine(SourceDir, f))
Continue
End If
Else
fName = f
End If
Log(" ") : Log(">>>>>>>>> PROCESS JS FILE: " & File.Combine(SourceDir, f))
Log("Minified JS file name: " & fName)
mInternalOperation = True
''' Wait For (MinifyFileToFileAsync (SourceDir, f, DestDir, fName)) Complete (Success As Boolean)
MinifyFileToFileAsync (SourceDir, f, DestDir, fName)
Wait For Compressor_FileComplete (Success As Boolean, jsItem As MinifiedFileItem)
Log("JS Returned from MinifyFileToFileAsync")
If Success Then
mFolderFilesOriginalSize = mFolderFilesOriginalSize + jsItem.OriginalSize
mFolderFilesMinifiedSize = mFolderFilesMinifiedSize + jsItem.MinifiedSize
Else
CallSubDelayed3(Me, mEventName & "_FolderComplete", False, Null)
End If
Else If f.EndsWith(".css") Then
If UseMinPrefix Then
If f.ToLowerCase.Contains(".min") = False Then
fName = f.SubString2(0, f.IndexOf(".css")) & ".min.css"
Else
Log("CSS File already minified. Skip it: " & File.Combine(SourceDir, f))
Continue
End If
Else
fName = f
End If
Log(" ") : Log(">>>>>>>>> PROCESS CSS FILE: " & File.Combine(SourceDir, f))
Log("Minified CSS file name: " & fName)
mInternalOperation = True
''' Wait For (MinifyFileToFileAsync (SourceDir, f, DestDir, fName)) Complete (Success As Boolean)
MinifyFileToFileAsync (SourceDir, f, DestDir, fName)
Wait For Compressor_FileComplete (Success As Boolean, cssItem As MinifiedFileItem)
Log("CSS Returned from MinifyFileToFileAsync")
If Success Then
mFolderFilesOriginalSize = mFolderFilesOriginalSize + cssItem.OriginalSize
mFolderFilesMinifiedSize = mFolderFilesMinifiedSize + cssItem.MinifiedSize
Else
' If SubExists(Me, mEventName & "_FolderComplete") Then
CallSubDelayed3(Me, mEventName & "_FolderComplete", False, Null)
Return True
' End If
End If
End If
Else
Log("FOUND FOLDER: " & File.Combine(SourceDir,f))
' Recursive call to process subfolders
''' Wait For (MinifyAllFilesOnFolderInternalAsync (File.Combine(SourceDir, f), File.Combine(DestDir, f), UseMinPrefix)) Complete (FolderItem As MinifiedFolderItem) ' << RECURSIVELY CALL ITSELF
MinifyAllFilesOnFolderInternalAsync (File.Combine(SourceDir, f), File.Combine(DestDir, f), UseMinPrefix)
Wait For Compressor_FolderComplete (Success As Boolean, FolderItem As MinifiedFolderItem) ' << RECURSIVELY CALL ITSELF
Log("Returned from MinifyAllFilesOnFolderInternalAsync")
If Success = False Then
CallSubDelayed3(Me, mEventName & "_FolderComplete", False, Null)
Return True ' Ensure proper termination
End If
' Continue ' Should this be used to skip next iteration ???
End If
Next
Else
Log("ERROR. CANNOT LIST FILES")
' Return Null
CallSubDelayed3(Me, mEventName & "_FolderComplete", False, Null)
Return True ' Ensure proper termination
End If
' Call FolderComplete event only once after processing all files and subfolders
Dim FolderItem As MinifiedFolderItem
FolderItem.Initialize
' Sleep(1)
Log(" ") : Log ("FOLDER MINIFICATION END. SHOULD ONLY CALLED AT END WHEN PROCESSED RECURSIVELY FOLDERS, SUBFOLDERS AND FILES ONE BY ONE WITH For Each") ' <<<<< THIS IS CALLED MORE TIMES BUT SHOULD ONLY CALLED ONE TIME
CallSubDelayed3(Me, mEventName & "_FolderComplete", True, FolderItem)
Return True ' Ensure proper termination
End Sub
Last edited: