在开发Solidity之前,许多开发人员都实现了Java,Go和Python。感觉就像在1980年代后期重返DeLorean。但是Solidity的稳定性非常有限。我在以下用例中使用了名为#ScriptIt的机长的NodeJS oracle:1.一个新用户获得256分。2.每个新调用,该用户的得分将减少log2。机长将直接从Solidity中运行NodeJS调用。 Docker容器,然后将结果返回到您的合同中。智能合约异步连接将从使用CaptainJS派生,其中包括异步调用和回调函数。要记住发生回调时的异步调用,您需要一个JobCounter以及作业ID和发送者地址之间的映射:uint JobCounter = 0;映射(uint =>地址)JobToSenderMap;该事件发生在以太坊中,当同步事务处于待处理的“开始”状态时,该事务只有两种状态:失败或成功。异步事务将要求在发出事件时通知用户事务是挂起,成功还是失败。因此,您定义了这些事件中的三个,每个事件至少应包含发送者地址:事件GetPoints_Success(地址发送者,uint点);事件GetPoints_Pending(地址发送者);事件GetPoints_Failed(地址发送方,字符串ErrorMsg);函数以太坊芳芳的默认模式是每个用户调用合约函数并支付在同步事务处理环境中执行代码所需的GAS。但是现在我们有了一个异步事务处理环境,这意味着在终止同步函数调用之后,将需要更多的资源。因此,您的功能必须是可付款的,并且您的第一项检查必须是验证用户是否已转移了足够的额外汽油费:uint GasRequired = DEFAULT_GAS_UNITS * tx.gasprice + 70 szabo; require(msg.value =“ = GasRequired,”请发送一些额外的气体...“);在此演示用例中,我们需要将usingCaptainJS中定义的默认汽油单位乘以当前交易汽油价格再加上70 Szabo的交易费用。一旦用户发送了足够的气体,您就可以根据GitHub上的队长说明调用mathjs的log2函数:Run(JobCounter,concat(“ math:log2(”,uintToString(PointsPerUser [msg.sender])) ,“)”),“”,“”,1,DEFAULT_GAS_UNITS,tx.gasprice);发出GetPoints_Pending(msg.sender);调用运行(...)后,必须发出一个未决事件。如果对运行(...)的调用失败,则同步调用将失败。回调一旦机长计算出用户点的log2值,他将通过调用CaptainsResult函数将结果发送回合同。通过仅添加CaptainsOrdersAllowed来确保只有队长调用此函数。确保在函数结束时发出成功事件。 funcTIon CaptainsResult(uint JobCounter,字符串Log2Result)仅限于外部CaptainsOrdersAllowed {//异步调用地址发送者的返回= JobToSenderMap [JobCounter]; uint Points = StringToUint(Log2Result); PointsPerUser [sender] = Points; Emit GetPoints_Success; }如果船长无法调用您提交的代码(JavaScript代码中可能存在拼写错误),他将通过调用合同的CaptainsError函数来通知您。确保在函数结束时发出失败事件。 funcTIon CaptainsError(uint JobCounter,字符串ErrorMsg)外部onlyCaptainsOrdersAllowed {//异步调用地址发送者的返回= JobToSenderMap [JobCounter];发出GetPoints_Failed(sender,ErrorMsg);}这是完整的代码:实用注释^ 0.4.25; import “ ./UsingCaptainJS_v2.sol”;合同AsyncPattern正在使用CaptainJS {//标识异步调用uint JobCounter = 0;映射(uint =》地址)JobToSenderMap; //演示用例:每个sendermapping的点数(address =》 uint)PointsPerUser ; event GetPoints_Success(地址发送方,uint点); event GetPoints_Pending(地址发送方); event GetPoints_Failed(地址发送方,字符串ErrorMsg); funcTIon GetPoints()公共应付款{//确保为异步回调提供足够的气体uint GasRequired = DEFAULT_GAS_UNITS * tx .gasprice + 70 szabo; require(msg.value =“ = GasRequired,“请再发送一些额外的气体...”)); //记住此调用JobToSenderMap [++ JobCounter] = msg.sender; //进行数学运算,但要混合使用异步+异步..//每个用户在开始时都有256个点,每次下一次调用//都是其点的log2(PointsPerUser [msg.sender] == 0){//第一次调用! PointsPerUser [msg.sender] = 256; emit GetPoints_Success(msg.sender,256);} else {//每隔一个callRun(JobCounter,concat(“ math:log2(” ,, uintToString(PointsPerUser [msg.sender]]) ),“)”),“”,“”,1,DEFAULT_GAS_UNITS,tx.gasprice);发出GetPoints_Pending(msg.sender);}}功能CaptainsResult(uint JobCounter,字符串Log2Result)外部onlyCaptainsOrdersAllowe