M8Test Help

入门

异步编程模式

这是本库最最重要的概念。所有异步操作(如 delay, async)都会立即返回一个 Deferred 对象,而不会暂停代码执行。任何需要在该异步操作完成后执行的逻辑,都必须通过 .then() 方法链接到 Deferred 对象上。

import com.m8test.script.GlobalVariables.* _threads.getMain().setBackground(true) val scope = _coroutines.newScope(null) // ----------------- ❌ 错误示范:同步思维 ----------------- // 这种写法是无效的,因为 delay 不会阻塞代码 // 修复:移除 lambda 参数 aScope,直接使用 implicit this 调用 delay scope.launch(null, null) { delay(1000) _console.log("这行日志会立刻打印,而不是在1秒后!") } // ----------------- ✅ 正确示范:异步链式思维 ----------------- // 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 // .then 的回调是 (CoroutineScope, T) -> Deferred<R>,需要参数,所以这里是对的 scope.delay(1000).then { aScope, result -> _console.log("这行日志会在1秒后正确打印。") // then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 aScope.resolve(null) }
$threads.getMain().setBackground(true) def scope = $coroutines.newScope(null) // ----------------- ❌ 错误示范:同步思维 ----------------- // 这种写法是无效的,因为 delay 不会阻塞代码 scope.launch(null, null, { aScope -> aScope.delay(1000) $console.log("这行日志会立刻打印,而不是在1秒后!") }) // ----------------- ✅ 正确示范:异步链式思维 ----------------- // 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 scope.delay(1000).then({ aScope, result -> $console.log("这行日志会在1秒后正确打印。") // then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 aScope.resolve(null) })
$threads.getMain().setBackground(true); const scope = $coroutines.newScope(null); // ----------------- ❌ 错误示范:同步思维 ----------------- // 这种写法是无效的,因为 delay 不会阻塞代码 scope.launch(null, null, aScope => { aScope.delay(1000); $console.log("这行日志会立刻打印,而不是在1秒后!"); }); // ----------------- ✅ 正确示范:异步链式思维 ----------------- // 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 scope.delay(1000).then((aScope, result) => { $console.log("这行日志会在1秒后正确打印。"); // then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 return aScope.resolve(null); });
_threads:getMain():setBackground(true) local scope = _coroutines:newScope(nil) -- ----------------- ❌ 错误示范:同步思维 ----------------- -- 这种写法是无效的,因为 delay 不会阻塞代码 scope:launch(nil, nil, function(aScope) aScope:delay(1000) _console:log("这行日志会立刻打印,而不是在1秒后!") end) -- ----------------- ✅ 正确示范:异步链式思维 ----------------- -- 所有依赖于前一个异步操作结果的代码,都必须放入 ._then() 闭包中 scope:delay(1000):_then(function(aScope, result) _console:log("这行日志会在1秒后正确打印。") -- _then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 return aScope:resolve(nil) end)
<?php /** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */ global $threads; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; $threads->getMain()->setBackground(true); $scope = $coroutines->newScope(function ($context) { $context->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); // ----------------- ❌ 错误示范:同步思维 ----------------- // 这种写法是无效的,因为 delay 不会阻塞代码 $scope->launch(null, null, function ($aScope) { global $console; $aScope->delay(1000); $console->log(javaString("这行日志会立刻打印,而不是在1秒后!")); }); // ----------------- ✅ 正确示范:异步链式思维 ----------------- // 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 $scope->delay(1000)->then(function ($aScope, $result) { global $console; $console->log(javaString("这行日志会在1秒后正确打印。")); // then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 return $aScope->resolve(null); });
# 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _threads _threads.getMain().setBackground(True) # 被转换为 Python 的嵌套 lambda 表达式 scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda dispatchers: dispatchers.getScriptMain()) ) # ----------------- ❌ 错误示范:同步思维 ----------------- # 这种写法是无效的,因为 delay 不会阻塞代码 scope.launch(None, None, lambda aScope: ( aScope.delay(1000), _console.log("这行日志会立刻打印,而不是在1秒后!") )) # ----------------- ✅ 正确示范:异步链式思维 ----------------- # 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 scope.delay(1000).then(lambda aScope, result: ( _console.log("这行日志会在1秒后正确打印。"), # then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 aScope.resolve(None) )[-1])
# encoding: utf-8 $threads.getMain().setBackground(true) scope = $coroutines.newScope(nil) # ----------------- ❌ 错误示范:同步思维 ----------------- # 这种写法是无效的,因为 delay 不会阻塞代码 scope.launch(nil, nil) do |aScope| aScope.delay(1000) $console.log("这行日志会立刻打印,而不是在1秒后!") end # ----------------- ✅ 正确示范:异步链式思维 ----------------- # 所有依赖于前一个异步操作结果的代码,都必须放入 .then() 闭包中 scope.delay(1000).then do |aScope, result| $console.log("这行日志会在1秒后正确打印。") # then 闭包必须返回一个新的 Deferred,即使没有有意义的结果 aScope.resolve(nil) end

“即发即忘”的异步任务

当你需要执行一个后台任务,但又不关心它的返回值时(例如,发送一条日志、更新一个文件),scope.launch() 是最佳选择。

import com.m8test.script.GlobalVariables.* /* * 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 */ // --- 样板代码 --- _threads.getMain().setBackground(true) val scope = _coroutines.newScope(null) _console.log("在 launch 调用之前。") // 使用 scope.launch() 启动一个“即发即忘”的协程 // 修复:移除 lambda 参数,直接调用 delay scope.launch(null, null) { _console.log("协程已经开始执行...") // 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> delay(1500).then { innerScope, _ -> // 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 _console.log("延时结束,协程任务完成!") // 最佳实践:then 闭包必须返回一个 Deferred。 // 对于没有实际返回值的操作,使用 innerScope.resolve(null) 来创建一个已完成的 Deferred。 innerScope.resolve(null) } } _console.log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。")
/* * 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 */ // --- 样板代码 --- $threads.getMain().setBackground(true) def scope = $coroutines.newScope(null) $console.log("在 launch 调用之前。") // 使用 scope.launch() 启动一个“即发即忘”的协程 scope.launch(null, null, { coroutineScope -> $console.log("协程已经开始执行...") // 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> coroutineScope.delay(1500).then({ innerScope, _ -> // 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 $console.log("延时结束,协程任务完成!") // 最佳实践:then 闭包必须返回一个 Deferred。 // 对于没有实际返回值的操作,使用 innerScope.resolve(null) 来创建一个已完成的 Deferred。 innerScope.resolve(null) }) }) $console.log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。")
/* * 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 */ // --- 样板代码 --- $threads.getMain().setBackground(true); const scope = $coroutines.newScope(null); $console.log("在 launch 调用之前。"); // 使用 scope.launch() 启动一个“即发即忘”的协程 scope.launch(null, null, coroutineScope => { $console.log("协程已经开始执行..."); // 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> coroutineScope.delay(1500).then((innerScope, _) => { // 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 $console.log("延时结束,协程任务完成!"); // 最佳实践:then 闭包必须返回一个 Deferred。 // 对于没有实际返回值的操作,使用 innerScope.resolve(null) 来创建一个已完成的 Deferred。 return innerScope.resolve(null); }); }); $console.log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。");
--[[ * 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 ]] -- --- 样板代码 --- _threads:getMain():setBackground(true) local scope = _coroutines:newScope(nil) _console:log("在 launch 调用之前。") -- 使用 scope:launch() 启动一个“即发即忘”的协程 scope:launch(nil, nil, function(coroutineScope) _console:log("协程已经开始执行...") -- 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> coroutineScope:delay(1500):_then(function(innerScope, _) -- 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 _console:log("延时结束,协程任务完成!") -- 最佳实践:_then 闭包必须返回一个 Deferred。 -- 对于没有实际返回值的操作,使用 innerScope:resolve(nil) 来创建一个已完成的 Deferred。 return innerScope:resolve(nil) end) end) _console:log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。")
<?php /** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */ global $threads; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /* * 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 */ // --- 样板代码 --- $threads->getMain()->setBackground(true); $scope = $coroutines->newScope(function ($context) { $context->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); $console->log(javaString("在 launch 调用之前。")); // 使用 scope.launch() 启动一个“即发即忘”的协程 $scope->launch(null, null, function ($coroutineScope) { global $console; $console->log(javaString("协程已经开始执行...")); // 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> $coroutineScope->delay(1500)->then(function ($innerScope, $_) { global $console; // 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 $console->log(javaString("延时结束,协程任务完成!")); // 最佳实践:then 闭包必须返回一个 Deferred。 // 对于没有实际返回值的操作,使用 innerScope.resolve(null) 来创建一个已完成的 Deferred。 return $innerScope->resolve(null); }); }); $console->log(javaString("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。"));
# # 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 # from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines # --- 样板代码 --- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _threads _threads.getMain().setBackground(True) # 使用您指定的 scope 创建方式 scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda dispatchers: dispatchers.getScriptMain()) ) _console.log("在 launch 调用之前。") # 使用 scope.launch() 启动一个“即发即忘”的协程 scope.launch(None, None, lambda coroutineScope: ( _console.log("协程已经开始执行..."), # 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> coroutineScope.delay(1500).then(lambda innerScope, _: ( # 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 _console.log("延时结束,协程任务完成!"), # 最佳实践:then 闭包必须返回一个 Deferred。 # 对于没有实际返回值的操作,使用 innerScope.resolve(null) 来创建一个已完成的 Deferred。 innerScope.resolve(None) )[-1]) )) _console.log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。")
# encoding: utf-8 # # 完整示例 2.1: 使用 launch 执行一个简单的后台延时任务 # # --- 样板代码 --- $threads.getMain().setBackground(true) scope = $coroutines.newScope(nil) $console.log("在 launch 调用之前。") # 使用 scope.launch() 启动一个“即发即忘”的协程 scope.launch(nil, nil) do |coroutineScope| $console.log("协程已经开始执行...") # 调用作用域提供的非阻塞 delay 函数,它会立即返回一个 Deferred<Unit> # Ruby 中 _ 也是有效的参数名,表示不关心该参数 coroutineScope.delay(1500).then do |innerScope, _| # 这个闭包内的代码,将在1.5秒延迟结束后被调度执行 $console.log("延时结束,协程任务完成!") # 最佳实践:then 闭包必须返回一个 Deferred。 # 对于没有实际返回值的操作,使用 innerScope.resolve(nil) 来创建一个已完成的 Deferred。 innerScope.resolve(nil) end end $console.log("在 launch 调用之后。注意这行日志会立刻打印,脚本不会在此处等待。")

获取结果:async 与 Deferred

当你的异步任务需要计算并返回一个结果时,使用 scope.async()。它会返回一个 Deferred 对象,T 是你期望的结果类型。Deferred 是一个对未来结果的承诺。

Deferred 的核心 API

  • .then({ scope, result -> ... }): 当 Deferred 成功完成时调用。result 是上一个异步任务的返回值。此闭包必须返回一个新的 Deferred 对象。

  • .onError({ error -> ... }): 当 Deferred 失败时调用。error 是导致失败的异常对象。

  • .onComplete(): 无论成功还是失败,在 Deferred 完成时总会调用。常用于资源清理。

获取简单的异步结果

import com.m8test.script.GlobalVariables.* /* * 完整示例 3.2: 使用 async 获取一个模拟的用户数据 */ // --- 样板代码 --- _threads.getMain().setBackground(true) val scope = _coroutines.newScope(null) _console.log("准备开始异步获取用户数据...") // scope.async 启动一个会返回结果的协程 // 修复:移除 lambda 参数 val userDeferred = scope.async(null, null) { // async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 // 这个 Map 将成为 userDeferred 的未来结果 mapOf("id" to "user-001", "name" to "张三") } // 链接 .then 来处理成功的结果 userDeferred.then { innerScope, user -> // Kotlin 中 Map 取值需要用 [] 或 get _console.log("成功获取到用户数据!用户名: " + user["name"]) // 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then val welcomeMessage = "欢迎您," + user["name"] innerScope.resolve(welcomeMessage) }.then { innerScope, message -> _console.log("处理后的消息: " + message) // 链条的末端也需要返回一个 Deferred innerScope.resolve(null) }.onError { error -> // 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 _console.error("获取用户数据时发生错误: " + error.getMessage()) }
/* * 完整示例 3.2: 使用 async 获取一个模拟的用户数据 */ // --- 样板代码 --- $threads.getMain().setBackground(true) def scope = $coroutines.newScope(null) $console.log("准备开始异步获取用户数据...") // scope.async 启动一个会返回结果的协程 def userDeferred = scope.async(null, null, { coroutineScope -> // async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 // 这个 Map 将成为 userDeferred 的未来结果 [id: "user-001", name: "张三"] }) // 链接 .then 来处理成功的结果 userDeferred.then({ innerScope, user -> $console.log("成功获取到用户数据!用户名: " + user.name) // 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then def welcomeMessage = "欢迎您," + user.name innerScope.resolve(welcomeMessage) }).then({ innerScope, message -> $console.log("处理后的消息: " + message) // 链条的末端也需要返回一个 Deferred innerScope.resolve(null) }).onError({ error -> // 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 $console.error("获取用户数据时发生错误: " + error.getMessage()) })
/* * 完整示例 3.2: 使用 async 获取一个模拟的用户数据 */ // --- 样板代码 --- $threads.getMain().setBackground(true); const scope = $coroutines.newScope(null); $console.log("准备开始异步获取用户数据..."); // scope.async 启动一个会返回结果的协程 const userDeferred = scope.async(null, null, coroutineScope => { // async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 // 这个 Map 将成为 userDeferred 的未来结果 return {id: "user-001", name: "张三"}; }); // 链接 .then 来处理成功的结果 userDeferred.then((innerScope, user) => { $console.log("成功获取到用户数据!用户名: " + user.name); // 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then const welcomeMessage = "欢迎您," + user.name; return innerScope.resolve(welcomeMessage); }).then((innerScope, message) => { $console.log("处理后的消息: " + message); // 链条的末端也需要返回一个 Deferred return innerScope.resolve(null); }).onError(error => { // 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 $console.error("获取用户数据时发生错误: " + error.getMessage()); });
--[[ * 完整示例 3.2: 使用 async 获取一个模拟的用户数据 ]] -- --- 样板代码 --- _threads:getMain():setBackground(true) local scope = _coroutines:newScope(nil) _console:log("准备开始异步获取用户数据...") -- scope:async 启动一个会返回结果的协程 local userDeferred = scope:async(nil, nil, function(coroutineScope) -- async 的闭包会隐式返回最后一行的结果,这里是一个 Lua table 对象 -- Lua-Java 桥接器会自动将其转为 Map, 这个 table 将成为 userDeferred 的未来结果 return { id = "user-001", name = "张三" } end) -- 链接 ._then 来处理成功的结果 userDeferred:_then(function(innerScope, user) _console:log("成功获取到用户数据!用户名: " .. user.name) -- 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 _then local welcomeMessage = "欢迎您," .. user.name return innerScope:resolve(welcomeMessage) end):_then(function(innerScope, message) _console:log("处理后的消息: " .. message) -- 链条的末端也需要返回一个 Deferred return innerScope:resolve(nil) end):onError(function(error) -- 如果 async 内部或任何一个 _then 环节抛出异常,这里会捕获到 _console:error("获取用户数据时发生错误: " .. error:getMessage()) end)
<?php /** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */ global $threads; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /* * 完整示例 3.2: 使用 async 获取一个模拟的用户数据 */ // --- 样板代码 --- $threads->getMain()->setBackground(true); $scope = $coroutines->newScope(function ($context) { $context->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); $console->log(javaString("准备开始异步获取用户数据...")); // scope.async 启动一个会返回结果的协程 $userDeferred = $scope->async(null, null, function ($coroutineScope) { // async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 // 这个 Map 将成为 userDeferred 的未来结果 return ['id' => javaString("user-001"), 'name' => javaString("张三")]; }); // 链接 .then 来处理成功的结果 $userDeferred->then(function ($innerScope, $user) { global $console; $console->log(javaString("成功获取到用户数据!用户名: ") . $user['name']); // 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then $welcomeMessage = javaString("欢迎您,") . $user['name']; return $innerScope->resolve($welcomeMessage); })->then(function ($innerScope, $message) { global $console; $console->log(javaString("处理后的消息: ") . $message); // 链条的末端也需要返回一个 Deferred return $innerScope->resolve(null); })->onError(function ($error) { global $console; // 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 $console->error(javaString("获取用户数据时发生错误: ") . $error->getMessage()); });
# # 完整示例 3.2: 使用 async 获取一个模拟的用户数据 # # --- 样板代码 --- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _threads from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _console _threads.getMain().setBackground(True) # 使用您指定的 scope 创建方式 scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda dispatchers: dispatchers.getScriptMain()) ) _console.log("准备开始异步获取用户数据...") # scope.async 启动一个会返回结果的协程 userDeferred = scope._async(None, None, lambda coroutineScope: ( # async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 # 这个 Map 将成为 userDeferred 的未来结果 # Groovy 的 [key: value] 映射转换为 Python 的 {'key': value} 字典 {'id': "user-001", 'name': "张三"} )) # 链接 .then 来处理成功的结果 userDeferred.then(lambda innerScope, user: ( # Groovy 的 user.name 是对 Map 的便捷访问,Python 中使用 user['name'] _console.log("成功获取到用户数据!用户名: " + user['name']), # 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then (welcomeMessage := "欢迎您," + user['name']), innerScope.resolve(welcomeMessage) # 记住并应用新规则:返回元组的最后一个元素,确保 then 链的返回值正确 )[-1]).then(lambda innerScope, message: ( # 为了安全,对 message 使用 str() 转换 _console.log("处理后的消息: " + str(message)), # 链条的末端也需要返回一个 Deferred innerScope.resolve(None) # 记住并应用新规则:返回元组的最后一个元素 )[-1]).onError(lambda error: ( # 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 _console.error("获取用户数据时发生错误: " + str(error.getMessage())) ))
# encoding: utf-8 # # 完整示例 3.2: 使用 async 获取一个模拟的用户数据 # # --- 样板代码 --- $threads.getMain().setBackground(true) scope = $coroutines.newScope(nil) $console.log("准备开始异步获取用户数据...") # scope.async 启动一个会返回结果的协程 userDeferred = scope.async(nil, nil) do |coroutineScope| # async 的闭包会隐式返回最后一行的结果,这里是一个 Map 对象 # 这个 Map 将成为 userDeferred 的未来结果 # Ruby 中 Hash 使用 {} {id: "user-001", name: "张三"} end # 链接 .then 来处理成功的结果 userDeferred.then do |innerScope, user| $console.log("成功获取到用户数据!用户名: " + user[:name]) # 我们可以对数据进行转换,并用 resolve 包装成新的 Deferred 传递给下一个 then welcomeMessage = "欢迎您," + user[:name] innerScope.resolve(welcomeMessage) end.then do |innerScope, message| $console.log("处理后的消息: " + message) # 链条的末端也需要返回一个 Deferred innerScope.resolve(nil) end.onError do |error| # 如果 async 内部或任何一个 then 环节抛出异常,这里会捕获到 $console.error("获取用户数据时发生错误: " + error.getMessage()) end

链式异步操作

.then 的真正威力在于,当它返回另一个由异步操作(如 async 或 delay)创建的 Deferred 时,整个链条会自动等待这个新的 Deferred 完成。这使得组织复杂的、有依赖关系的异步流程变得异常清晰。

import com.m8test.script.GlobalVariables.* /* * 完整示例 3.3 (已修正为完全非阻塞的链式实现): * 先获取用户信息,再根据用户信息获取其帖子列表 */ // --- 样板代码 --- _threads.getMain().setBackground(true) val scope = _coroutines.newScope(null) // --- 核心修正点 --- // 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 // 模拟的 API 函数 1: 获取用户 (已修正) // 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 val fetchUser = { userId: String -> _console.log("正在准备获取用户 " + userId + " 的信息 (延时500ms)...") // 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 scope.delay(500).then { s, _ -> // 2. 在延迟结束后,这个 .then 闭包被执行。 // 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 // 立即成功的 Deferred<Map> 并返回。 _console.log(" -> 用户信息延时获取完成。") s.resolve(mapOf("id" to userId, "name" to "用户" + userId)) } } // 模拟的 API 函数 2: 获取帖子 (已修正) // 同样,这个函数也直接返回一个 Deferred 链。 val fetchPosts = { user: Map<String, String> -> _console.log("正在准备获取 " + user["name"] + " 的帖子 (延时800ms)...") scope.delay(800).then { s, _ -> _console.log(" -> 帖子列表延时获取完成。") // 模拟一个可能发生的错误 if (user["id"] == "002") { // 修复:去掉 'builder ->',直接在 Lambda 中调用方法,此时 this 即为 builder val error = _exceptions.newThrowable { setMessageAndClassName("用户 " + user["name"] + " 的帖子列表为空或无权访问。", "java.io.IOException") } // 使用 s.reject() 创建并返回一个立即失败的 Deferred。 s.reject(error) } else { // 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 s.resolve(listOf("帖子一:协程入门", "帖子二:高级技巧")) } } } // --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- _console.log("准备开始执行主异步链...") fetchUser("001").then { innerScope, user -> // 此处 `user` 是正确的 Map 对象! _console.log("主链第一步:成功获取到用户 -> " + user["name"]) // 直接返回 fetchPosts 返回的 Deferred 对象。 // .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 fetchPosts(user) }.then { innerScope, posts -> // 此处 `posts` 是正确的 List 对象! _console.log("主链第二步:成功获取到帖子列表 -> " + posts) innerScope.resolve(null) }.onError { error -> // 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 _console.error("错误:在主链处理中发生异常 -> " + error.getMessage()) } // 同时测试一下失败路径 scope.delay(3000).then { s, _ -> _console.log("\n准备测试失败路径...") fetchUser("002").then { innerScope, user -> fetchPosts(user) }.onError { error -> _console.error("错误(失败路径测试):成功捕获到预期的异常 -> " + error.getMessage()) } }
/* * 完整示例 3.3 (已修正为完全非阻塞的链式实现): * 先获取用户信息,再根据用户信息获取其帖子列表 */ // --- 样板代码 --- $threads.getMain().setBackground(true) def scope = $coroutines.newScope(null) // --- 核心修正点 --- // 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 // 模拟的 API 函数 1: 获取用户 (已修正) // 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 def fetchUser = { userId -> $console.log("正在准备获取用户 " + userId + " 的信息 (延时500ms)...") // 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 scope.delay(500).then({ s, _ -> // 2. 在延迟结束后,这个 .then 闭包被执行。 // 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 // 立即成功的 Deferred<Map> 并返回。 $console.log(" -> 用户信息延时获取完成。") s.resolve([id: userId, name: "用户" + userId]) }) } // 模拟的 API 函数 2: 获取帖子 (已修正) // 同样,这个函数也直接返回一个 Deferred 链。 def fetchPosts = { user -> $console.log("正在准备获取 " + user.name + " 的帖子 (延时800ms)...") scope.delay(800).then({ s, _ -> $console.log(" -> 帖子列表延时获取完成。") // 模拟一个可能发生的错误 if (user.id == "002") { def error = $exceptions.newThrowable({ builder -> builder.setMessageAndClassName("用户 " + user.name + " 的帖子列表为空或无权访问。", "java.io.IOException") }) // 使用 s.reject() 创建并返回一个立即失败的 Deferred。 s.reject(error) } else { // 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 s.resolve(["帖子一:协程入门", "帖子二:高级技巧"]) } }) } // --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- $console.log("准备开始执行主异步链...") fetchUser("001").then({ innerScope, user -> // 此处 `user` 是正确的 Map 对象! $console.log("主链第一步:成功获取到用户 -> " + user.name) // 直接返回 fetchPosts 返回的 Deferred 对象。 // .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 fetchPosts(user) }).then({ innerScope, posts -> // 此处 `posts` 是正确的 List 对象! $console.log("主链第二步:成功获取到帖子列表 -> " + posts) innerScope.resolve(null) }).onError({ error -> // 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 $console.error("错误:在主链处理中发生异常 -> " + error.getMessage()) }) // 同时测试一下失败路径 scope.delay(3000).then({s, _ -> $console.log("\n准备测试失败路径...") fetchUser("002").then({ innerScope, user -> fetchPosts(user) }).onError({ error -> $console.error("错误(失败路径测试):成功捕获到预期的异常 -> " + error.getMessage()) }) })
/* * 完整示例 3.3 (已修正为完全非阻塞的链式实现): * 先获取用户信息,再根据用户信息获取其帖子列表 */ // --- 样板代码 --- $threads.getMain().setBackground(true); const scope = $coroutines.newScope(null); // --- 核心修正点 --- // 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 /** * 模拟的 API 函数 1: 获取用户 (已修正) * 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 * @param {string} userId * @returns {Deferred<{id: string, name: string}>} */ const fetchUser = userId => { $console.log("正在准备获取用户 " + userId + " 的信息 (延时500ms)..."); // 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 return scope.delay(500).then((s, _) => { // 2. 在延迟结束后,这个 .then 闭包被执行。 // 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 // 立即成功的 Deferred<Map> 并返回。 $console.log(" -> 用户信息延时获取完成。"); return s.resolve({id: userId, name: "用户" + userId}); }); }; /** * 模拟的 API 函数 2: 获取帖子 (已修正) * 同样,这个函数也直接返回一个 Deferred 链。 * @param {{id: string, name: string}} user * @returns {Deferred<string[]>} */ const fetchPosts = user => { $console.log("正在准备获取 " + user.name + " 的帖子 (延时800ms)..."); return scope.delay(800).then((s, _) => { $console.log(" -> 帖子列表延时获取完成。"); // 模拟一个可能发生的错误 if (user.id == "002") { const error = $exceptions.newThrowable(builder => { builder.setMessageAndClassName("用户 " + user.name + " 的帖子列表为空或无权访问。", "java.io.IOException"); }); // 使用 s.reject() 创建并返回一个立即失败的 Deferred。 return s.reject(error); } else { // 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 return s.resolve(["帖子一:协程入门", "帖子二:高级技巧"]); } }); }; // --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- $console.log("准备开始执行主异步链..."); fetchUser("001").then((innerScope, user) => { // 此处 `user` 是正确的 Map 对象! $console.log("主链第一步:成功获取到用户 -> " + user.name); // 直接返回 fetchPosts 返回的 Deferred 对象。 // .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 return fetchPosts(user); }).then((innerScope, posts) => { // 此处 `posts` 是正确的 List 对象! $console.log("主链第二步:成功获取到帖子列表 -> " + posts); return innerScope.resolve(null); }).onError(error => { // 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 $console.error("错误:在主链处理中发生异常 -> " + error.getMessage()); }); // 同时测试一下失败路径 scope.delay(3000).then((s, _) => { $console.log("\n准备测试失败路径..."); fetchUser("002").then((innerScope, user) => { return fetchPosts(user); }).onError(error => { $console.error("错误(失败路径测试):成功捕获到预期的异常 -> " + error.getMessage()); }); });
--[[ * 完整示例 3.3 (已修正为完全非阻塞的链式实现): * 先获取用户信息,再根据用户信息获取其帖子列表 ]] -- --- 样板代码 --- _threads:getMain():setBackground(true) local scope = _coroutines:newScope(nil) -- --- 核心修正点 --- -- 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 -- 模拟的 API 函数 1: 获取用户 (已修正) -- 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 local fetchUser = function(userId) _console:log("正在准备获取用户 " .. userId .. " 的信息 (延时500ms)...") -- 1. 以 scope:delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 return scope:delay(500):_then(function(s, _) -- 2. 在延迟结束后,这个 ._then 闭包被执行。 -- 3. 我们在这里创建用户数据,并用 s:resolve() 将其包装成一个新的、 -- 立即成功的 Deferred<Map> 并返回。 _console:log(" -> 用户信息延时获取完成。") return s:resolve({ id = userId, name = "用户" .. userId }) end) end -- 模拟的 API 函数 2: 获取帖子 (已修正) -- 同样,这个函数也直接返回一个 Deferred 链。 local fetchPosts = function(user) _console:log("正在准备获取 " .. user.name .. " 的帖子 (延时800ms)...") return scope:delay(800):_then(function(s, _) _console:log(" -> 帖子列表延时获取完成。") -- 模拟一个可能发生的错误 if user.id == "002" then local errorObj = _exceptions:newThrowable(function(builder) builder:setMessageAndClassName("用户 " .. user.name .. " 的帖子列表为空或无权访问。", "java.io.IOException") end) -- 使用 s:reject() 创建并返回一个立即失败的 Deferred。 return s:reject(errorObj) else -- 使用 s:resolve() 创建并返回一个立即成功的 Deferred。 return s:resolve(_iterables:listOf("帖子一:协程入门", "帖子二:高级技巧")) end end) end -- --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- _console:log("准备开始执行主异步链...") fetchUser("001"):_then(function(innerScope, user) -- 此处 `user` 是正确的 table 对象! _console:log("主链第一步:成功获取到用户 -> " .. user.name) -- 直接返回 fetchPosts 返回的 Deferred 对象。 -- ._then 会自动处理这个返回的 "Promise",等待它完成后再继续。 return fetchPosts(user) end):_then(function(innerScope, posts) -- 此处 `posts` 是正确的 List 对象! _console:log("主链第二步:成功获取到帖子列表 -> " .. tostring(posts)) return innerScope:resolve(nil) end):onError(function(error) -- 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 _console:error("错误:在主链处理中发生异常 -> " .. error:getMessage()) end) -- 同时测试一下失败路径 scope:delay(3000):_then(function(s, _) _console:log("\n准备测试失败路径...") fetchUser("002"):_then(function(innerScope, user) return fetchPosts(user) end):onError(function(error) _console:error("错误(失败路径测试):成功捕获到预期的异常 -> " .. error:getMessage()) end) end)
<?php /** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */ global $threads; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /** @var m8test_java\com\m8test\script\core\api\exception\Exceptions $exceptions */ global $exceptions; /* * 完整示例 3.3 (已修正为完全非阻塞的链式实现): * 先获取用户信息,再根据用户信息获取其帖子列表 */ // --- 样板代码 --- $threads->getMain()->setBackground(true); $scope = $coroutines->newScope(function ($context) { $context->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); // --- 核心修正点 --- // 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 // 模拟的 API 函数 1: 获取用户 (已修正) // 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 $fetchUser = function ($userId) use ($scope) { global $console; $console->log(javaString("正在准备获取用户 ") . $userId . javaString(" 的信息 (延时500ms)...")); // 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 return $scope->delay(500)->then(function ($s, $_) use ($userId) { global $console; // 2. 在延迟结束后,这个 .then 闭包被执行。 // 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 // 立即成功的 Deferred<Map> 并返回。 $console->log(javaString(" -> 用户信息延时获取完成。")); return $s->resolve(['id' => $userId, 'name' => javaString("用户") . $userId]); }); }; // 模拟的 API 函数 2: 获取帖子 (已修正) // 同样,这个函数也直接返回一个 Deferred 链。 $fetchPosts = function ($user) use ($scope) { global $console, $exceptions; $console->log(javaString("正在准备获取 ") . $user['name'] . javaString(" 的帖子 (延时800ms)...")); return $scope->delay(800)->then(function ($s, $_) use ($user) { global $console, $exceptions; $console->log(javaString(" -> 帖子列表延时获取完成。")); // 模拟一个可能发生的错误 if ($user['id'] == "002") { $error = $exceptions->newThrowable(function ($builder) use ($user) { $builder->setMessageAndClassName(javaString("用户 ") . $user['name'] . javaString(" 的帖子列表为空或无权访问。"), javaString("java.io.IOException")); }); // 使用 s.reject() 创建并返回一个立即失败的 Deferred。 return $s->reject($error); } else { // 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 return $s->resolve([javaString("帖子一:协程入门"), javaString("帖子二:高级技巧")]); } }); }; // --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- $console->log(javaString("准备开始执行主异步链...")); $fetchUser("001")->then(function ($innerScope, $user) use ($fetchPosts) { global $console; // 此处 `user` 是正确的 Map 对象! $console->log(javaString("主链第一步:成功获取到用户 -> ") . $user['name']); // 直接返回 fetchPosts 返回的 Deferred 对象。 // .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 return $fetchPosts($user); })->then(function ($innerScope, $posts) { global $console; // 此处 `posts` 是正确的 List 对象! $console->log(javaString("主链第二步:成功获取到帖子列表 -> "), $posts); // Assuming PHP array to string return $innerScope->resolve(null); })->onError(function ($error) { global $console; // 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 $console->error(javaString("错误:在主链处理中发生异常 -> ") . $error->getMessage()); }); // 同时测试一下失败路径 $scope->delay(3000)->then(function ($s, $_) use ($fetchUser, $fetchPosts) { global $console; $console->log(javaString("\n准备测试失败路径...")); $fetchUser("002")->then(function ($innerScope, $user) use ($fetchPosts) { return $fetchPosts($user); })->onError(function ($error) { global $console; $console->error(javaString("错误(失败路径测试):成功捕获到预期的异常 -> ") . $error->getMessage()); }); return $s->resolve(null); // The outer then needs to return a deferred. });
# # 完整示例 3.3 (已修正为完全非阻塞的链式实现): # 先获取用户信息,再根据用户信息获取其帖子列表 # from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _exceptions # --- 样板代码 --- # 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _threads _threads.getMain().setBackground(True) # 使用您指定的 scope 创建方式 scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda dispatchers: dispatchers.getScriptMain()) ) # --- 核心修正点 --- # 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 # 模拟的 API 函数 1: 获取用户 (已修正) # 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 def fetchUser(userId): _console.log("正在准备获取用户 " + str(userId) + " 的信息 (延时500ms)...") # 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 return scope.delay(500).then(lambda s, _: ( # 2. 在延迟结束后,这个 .then 闭包被执行。 # 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 # 立即成功的 Deferred<Map> 并返回。 _console.log(" -> 用户信息延时获取完成。"), s.resolve({'id': userId, 'name': "用户" + str(userId)}) )[-1]) # 模拟的 API 函数 2: 获取帖子 (已修正) # 同样,这个函数也直接返回一个 Deferred 链。 def fetchPosts(user): _console.log("正在准备获取 " + user['name'] + " 的帖子 (延时800ms)...") return scope.delay(800).then(lambda s, _: ( _console.log(" -> 帖子列表延时获取完成。"), # 模拟一个可能发生的错误 # 使用 Python 的条件表达式 (三元运算符) 来处理 if/else 逻辑 (s.reject( _exceptions.newThrowable(lambda builder: builder.setMessageAndClassName( "用户 " + user['name'] + " 的帖子列表为空或无权访问。", "java.io.IOException") ) ) if user['id'] == "002" else # 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 s.resolve(["帖子一:协程入门", "帖子二:高级技巧"])) )[-1]) # --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- _console.log("准备开始执行主异步链...") fetchUser("001").then(lambda innerScope, user: ( # 此处 `user` 是正确的 Map 对象! # Groovy 的 user.name 变为 Python 的 user['name'] _console.log("主链第一步:成功获取到用户 -> " + user['name']), # 直接返回 fetchPosts 返回的 Deferred 对象。 # .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 fetchPosts(user) )[-1]).then(lambda innerScope, posts: ( # 此处 `posts` 是正确的 List 对象! # 使用 str() 确保 posts 可以被安全地打印 _console.log("主链第二步:成功获取到帖子列表 -> " + str(posts)), innerScope.resolve(None) )[-1]).onError(lambda error: ( # 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 _console.error("错误:在主链处理中发生异常 -> " + str(error.getMessage())) )) # 同时测试一下失败路径 scope.delay(3000).then(lambda s, _: ( _console.log("\n准备测试失败路径..."), fetchUser("002").then( # 这里的 lambda 是单行表达式,可以直接返回 fetchPosts 的结果,无需元组 lambda innerScope, user: fetchPosts(user) ).onError( # 这里的 lambda 也是单行表达式 lambda error: _console.error("错误(失败路径测试):成功捕获到预期的异常 -> " + str(error.getMessage())) ) # 外层 then 只是为了触发任务,不需要返回链条,所以不需要 [-1] )[-1])
# encoding: utf-8 # # 完整示例 3.3 (已修正为完全非阻塞的链式实现): # 先获取用户信息,再根据用户信息获取其帖子列表 # # --- 样板代码 --- $threads.getMain().setBackground(true) scope = $coroutines.newScope(nil) # --- 核心修正点 --- # 我们不再在 async 内部创建链条,而是让函数本身就是链条的起点。 # 模拟的 API 函数 1: 获取用户 (已修正) # 这个函数现在直接返回一个从 delay 开始的 Deferred 链。 # Ruby 中使用 lambda 或 proc 定义可调用的闭包 fetchUser = lambda do |userId| $console.log("正在准备获取用户 " + userId + " 的信息 (延时500ms)...") # 1. 以 scope.delay(500) 作为链条的起点。它返回一个 Deferred<Unit>。 scope.delay(500).then do |s, _| # 2. 在延迟结束后,这个 .then 闭包被执行。 # 3. 我们在这里创建用户数据,并用 s.resolve() 将其包装成一个新的、 # 立即成功的 Deferred<Map> 并返回。 $console.log(" -> 用户信息延时获取完成。") s.resolve({id: userId, name: "用户" + userId}) end end # 模拟的 API 函数 2: 获取帖子 (已修正) # 同样,这个函数也直接返回一个 Deferred 链。 fetchPosts = lambda do |user| $console.log("正在准备获取 " + user[:name] + " 的帖子 (延时800ms)...") scope.delay(800).then do |s, _| $console.log(" -> 帖子列表延时获取完成。") # 模拟一个可能发生的错误 if user[:id] == "002" error = $exceptions.newThrowable do |builder| builder.setMessageAndClassName("用户 " + user[:name] + " 的帖子列表为空或无权访问。", "java.io.IOException") end # 使用 s.reject() 创建并返回一个立即失败的 Deferred。 s.reject(error) else # 使用 s.resolve() 创建并返回一个立即成功的 Deferred。 s.resolve(["帖子一:协程入门", "帖子二:高级技巧"]) end end end # --- 外部的异步链调用现在不仅能工作,而且其结构与内部实现完全一致! --- $console.log("准备开始执行主异步链...") # Ruby 中调用 lambda 需要使用 .call() fetchUser.call("001").then do |innerScope, user| # 此处 `user` 是正确的 Map 对象! $console.log("主链第一步:成功获取到用户 -> " + user[:name]) # 直接返回 fetchPosts 返回的 Deferred 对象。 # .then 会自动处理这个返回的 "Promise",等待它完成后再继续。 fetchPosts.call(user) end.then do |innerScope, posts| # 此处 `posts` 是正确的 List 对象! # Ruby 数组转字符串直接使用 to_s $console.log("主链第二步:成功获取到帖子列表 -> " + posts.to_s) innerScope.resolve(nil) end.onError do |error| # 这个 onError 可以捕获 fetchUser 或 fetchPosts 中任何一个环节的错误 $console.error("错误:在主链处理中发生异常 -> " + error.getMessage()) end # 同时测试一下失败路径 scope.delay(3000).then do |s, _| $console.log("\n准备测试失败路径...") fetchUser.call("002").then do |innerScope, user| fetchPosts.call(user) end.onError do |error| $console.error("错误(失败路径测试):成功捕获到预期的异常 -> " + error.getMessage()) end end

resolve 和 reject: 融入同步逻辑

scope.resolve(value) 和 scope.reject(error) 是将同步代码无缝融入异步链的关键工具。

  • scope.resolve(value): 将一个已知的值包装成一个立即成功的 Deferred。

  • scope.reject(error): 将一个已知错误包装成一个立即失败的 Deferred。

import com.m8test.script.GlobalVariables.* import com.m8test.script.core.api.coroutines.Deferred val scope = _coroutines.newScope(null) // 示例:从缓存或网络获取数据 val cachedData: String? = null // or "缓存数据" val dataDeferred: Deferred<String?> = if (cachedData != null) { _console.log("命中了缓存!") scope.resolve(cachedData) // 直接使用缓存 } else { _console.log("缓存未命中,从网络获取...") // 修复:async 块移除显式参数 ss -> scope.delay(5000).then { s, _ -> s.async(null, null) { "从网络获取的数据" } } } dataDeferred.then { s, data -> _console.log("最终获取到的数据: " + data) s.resolve(null) } _threads.getMain().setBackground(true)
import com.m8test.script.core.api.coroutines.Deferred def scope = $coroutines.newScope(null) // 示例:从缓存或网络获取数据 def cachedData = null // or "缓存数据" Deferred<String> dataDeferred = null if (cachedData != null) { $console.log("命中了缓存!") dataDeferred = scope.resolve(cachedData) // 直接使用缓存 } else { $console.log("缓存未命中,从网络获取...") dataDeferred = scope.delay(5000).then({ s, _ -> s.async(null, null) { ss -> "从网络获取的数据" } }) } dataDeferred.then({ s, data -> $console.log("最终获取到的数据: " + data) s.resolve(null) }) $threads.getMain().setBackground(true)
const scope = $coroutines.newScope(null); // 示例:从缓存或网络获取数据 let cachedData = null; // or "缓存数据" /** @type {Deferred<string>} */ let dataDeferred = null; if (cachedData != null) { $console.log("命中了缓存!"); dataDeferred = scope.resolve(cachedData); // 直接使用缓存 } else { $console.log("缓存未命中,从网络获取..."); dataDeferred = scope.delay(5000).then((s, _) => s.async(null, null, ss => "从网络获取的数据")); } dataDeferred.then((s, data) => { $console.log("最终获取到的数据: " + data); return s.resolve(null); }); $threads.getMain().setBackground(true);
local scope = _coroutines:newScope(nil) -- 示例:从缓存或网络获取数据 local cachedData = nil -- or "缓存数据" local dataDeferred = nil if cachedData ~= nil then _console:log("命中了缓存!") dataDeferred = scope:resolve(cachedData) -- 直接使用缓存 else _console:log("缓存未命中,从网络获取...") dataDeferred = scope:delay(5000):_then(function(s, _) return s:async(nil, nil, function(ss) return "从网络获取的数据" end) end) end dataDeferred:_then(function(s, data) _console:log("最终获取到的数据: " .. data) return s:resolve(nil) end) _threads:getMain():setBackground(true)
<?php /** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */ global $threads; /** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */ global $coroutines; /** @var m8test_java\com\m8test\script\core\api\console\Console $console */ global $console; /** @var m8test_java\com\m8test\script\core\api\coroutines\Deferred $dataDeferred */ $scope = $coroutines->newScope(function ($context) { $context->setDispatcher(function ($dispatchers) { return $dispatchers->getScriptMain(); }); }); // 示例:从缓存或网络获取数据 $cachedData = null; // or javaString("缓存数据") $dataDeferred = null; if ($cachedData != null) { $console->log(javaString("命中了缓存!")); $dataDeferred = $scope->resolve($cachedData); // 直接使用缓存 } else { $console->log(javaString("缓存未命中,从网络获取...")); $dataDeferred = $scope->delay(5000)->then(function ($s, $_) { return $s->async(null, null, function ($ss) { return javaString("从网络获取的数据"); }); }); } $dataDeferred->then(function ($s, $data) { global $console; $console->log(javaString("最终获取到的数据: ") . $data); return $s->resolve(null); }); $threads->getMain()->setBackground(true);
# 导入所需的全局变量 from m8test_java.com.m8test.script.GlobalVariables import _console from m8test_java.com.m8test.script.GlobalVariables import _coroutines from m8test_java.com.m8test.script.GlobalVariables import _threads # 导入所需的Java类 scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain())) # 示例:从缓存或网络获取数据 cachedData = None # or "缓存数据" dataDeferred = None # Use Python's conditional expression for if/else if cachedData is not None: _console.log("命中了缓存!") dataDeferred = scope.resolve(cachedData) # 直接使用缓存 else: _console.log("缓存未命中,从网络获取...") # Remember to use _async for scope.async dataDeferred = scope.delay(5000).then(lambda s, _: s._async(None, None, lambda ss: "从网络获取的数据") ) dataDeferred.then(lambda s, data: ( _console.log("最终获取到的数据: " + str(data)), s.resolve(None) )[-1]) _threads.getMain().setBackground(True)
# encoding: utf-8 # import com.m8test.script.core.api.coroutines.Deferred # Ruby不需要显式import泛型类型 scope = $coroutines.newScope(nil) # 示例:从缓存或网络获取数据 cachedData = nil # or "缓存数据" dataDeferred = nil if cachedData != nil $console.log("命中了缓存!") dataDeferred = scope.resolve(cachedData) # 直接使用缓存 else $console.log("缓存未命中,从网络获取...") dataDeferred = scope.delay(5000).then { |s, _| s.async(nil, nil) { |ss| "从网络获取的数据" } } end dataDeferred.then do |s, data| $console.log("最终获取到的数据: " + data) s.resolve(nil) end $threads.getMain().setBackground(true)
09 December 2025