PureScript FFI与Aff Monad问题:为何定义的effect从未执行?
Hey there! Let's walk through some common fixes for this Aff Monad FFI issue you're hitting—super common when you're starting out with PureScript, so don't sweat it.
1. Double-check your FFI implementation properly constructs an Aff instance
Aff isn't just a regular async function—it relies on notifying the PureScript runtime when it's done. A common mistake is forgetting to trigger the success (or failure) callback that makeAff expects.
For example, if your FFI code looks like this (wrong):
exports.delayedLog = function() { setTimeout(() => console.log("keyMessage"), 1000); };
This won't work because it never tells the Aff runtime that the async operation completed. Instead, your FFI needs to return a function that accepts success and failure callbacks, and invokes success once the work is done:
exports.delayedLog = function() { return function(success, failure) { setTimeout(function() { console.log("keyMessage"); success(); // Critical: Signal the Aff computation is finished }, 1000); // Return a cleanup function (empty here since we don't need to cancel the timeout) return function() {}; }; };
2. Make sure you're actually running the Aff computation
Aff is lazy—defining an Aff value doesn't execute it automatically. You need to explicitly launch it using functions like launchAff_ (for fire-and-forget) or runAff (if you need to handle the result/errors).
If your Main.purs only has something like:
foreign import delayedLog :: Aff Unit main = delayedLog -- Wrong! This doesn't run the Aff
That's why your program hangs. Instead, convert it to an Effect and run it:
module Main where import Effect (Effect) import Effect.Aff (Aff, launchAff_) import Effect.Console (log) foreign import delayedLog :: Aff Unit main :: Effect Unit main = launchAff_ delayedLog -- Correct: Launches the Aff computation
3. Verify your PureScript type signature matches the FFI
Ensure your foreign import has the correct type—if you accidentally wrote Effect Unit instead of Aff Unit, the runtime will misbehave. Double-check that your import line looks like:
foreign import delayedLog :: Aff Unit
4. Check for unhandled errors in the FFI
If your timeout logic throws an error (even a silent one) and you don't call the failure callback, the Aff computation will hang indefinitely. Add a try-catch in your FFI to handle this:
exports.delayedLog = function() { return function(success, failure) { setTimeout(function() { try { console.log("keyMessage"); success(); } catch (err) { failure(err); // Pass errors to the Aff runtime } }, 1000); return function() {}; }; };
You can also add error handling in PureScript with catchError to see if any errors are being swallowed:
main = launchAff_ $ delayedLog `catchError` \err -> log $ "Error: " <> show err
Give these steps a shot—chances are one of these is the culprit!
内容的提问来源于stack exchange,提问作者Nick Saunders

