00:00
好,我们继续往后面看,然后这又是一个直观的一个,这个应该怎么说呢?这就是一个理论性的东西啊,就是说我们平常在用WEB3跟我们的以太网节点做交互的时候,我们到底用的是同步调用还是异步调用呢?我们发送的是同步请求还是异步请求呢?一般情况来讲。特别是在这个0.20就是0.2几的这个版本以下的时候。WEB3GS它所有的这些API的调用基,呃,不是说所有的绝大多数默认的调用方式是同步调用。因为它最初的设计目的呢,主要是为了跟本地的RPC节点共同作用的,就是相当于就是自己本地起一个全节点,然后我连上去提供这样的服务,他一开始是这么去做的,所以说他有很多方式都是同步的方式。
01:02
其实大家之前我们在GA cons里边,大家应该还有印象,我们如果去做这这些操作,比方说。呃,我们这里已经有了ETH了,我们这里去get block number get block number啊。它本身就可以查block number对吧,或者我们可以get block number去。呃,大家可以看我这里,如果要是调用这个函数的话,它就返回的是一个on范,不知道大家试过没有试过这种方法,呃,等大家试的它能返回数字吗?呃,之前好像没有试出来过是吧?但是我们可以直接用这个block number1访问就访问到了,对吧?好像这就是一个本地的状态变量一样,但事实上我们的这个以太坊节点,大家想我们可能直接把它当一个本地的状态变量直接拿出来吗?
02:07
当前的这个区块高度。其实不太可能对吧,我们如果要是想拿到当前的区块高度,肯定是需要去查一下当前。以太坊节点上的状态的,我们一定会发一个请求,或者说发一个RPC调用,去问一下以太坊节点你现在的状态是怎么样的,你现在的区块高度是多少,它才能返回给我们,对吧?所以我们这种方式其实是发送了一个消息调用发送了一个请求的,只不过这个请求是一个。同步的请求。而且我们连的是本地节点,它返回很快,所以我们看起来好像它就是实时返回的,对吧,一敲它就回来了,一敲就回来了,就好像是我们本地有这个变量一样,那大家看到我刚才直接还他还有一个方法叫get block number,我们直接敲的时候发现他说这是一个方式,对吧,那我直接用方式调用方式后面加括号呢,他又说这是一个on fun。
03:11
那这个就就就我们好像就不知道这这玩意儿到底怎么回事呢,那其实这就是我们这里要跟大家介绍的啊。就是在WEB3GS它的设计里边,一开始最初设计的目的大部分是同步的HP请求,那同时呢,因为我们跟节点的通信本身并不是一个同步的过程。大家都都知道,我们既然是在发HTV请求嘛,那其实正常来讲肯定是一个异步的过程,我不是我一发出去之后就能马上得到响应,得到回答的,有时候我们现在连本地local host,那肯定快了,如果你连的是一个远远端的一个网络,一个节点的话,那肯定它是有一个延迟回复的。所以。
04:02
本身WEB3GS也支持异步调用,那它异步调用的方式是什么呢?一般就是在函数的最后一个参数位置上加一个回调函数。回调应该大家也比较熟悉了吧,学之前大家学这个前端学的时候讲过回调吧,讲过是吧,好,那这块不用再多说啊呃,对于这样的函数来说,它的回调函数就是可选的。所以它的一个状态就会是什么样呢,就会是我可以加上回调,也可以不加回调,加上回调之后就是一个义务请求不加回调呢。那就变成了一个同步请求,比如说这里很典型的一个就是get block。好,我们来看一下啊,这里举的一个例子就是就是ets.e.get block后面跟上一个数字,也就是说。
05:03
我们要拿到每一个区块给它一个高度,对吧,然后就是指定的那个区块高度的区块内容,我们现在看一下,大家之前其实应该是做过这样操作的啊,我们先就在这个pencil里面去试一下吧,因为这个简单一点,它默认已经有外餐了嘛,Get block,我我们直接这样get的话肯定有问题对吧?那我们现在已经是25了,我get block25看一下,大家看直接输入25的时候。他直接就返回这个区块的信息了。所以这种方式就是一个同步的请求方式,我们发出去之后直接阻塞柱进程,然后等它返回,然后把返回的内容直接给我们显示在控制台上,同步的方式,那如果要是异步的方式怎么来做呢?大家看这边写的啊。
06:00
就是在后边,在我们已经给了区块号之之后,再加入一个。回调函数,我们看后边这样的一个东西,就是一个回调函数,好,我们来写一下啊,回调函数是什么样的呢?大家看就是定义一个方式,然后它会有两个参数,在WEB3GS的0.2几的版本里面,它的回调函数的格式一般都是这样定义的,就是所谓的错误优先处理的一个一个原则来定义,它的回调函数是ever在前面,Result在后边,这就是它的回调函数的传参。然后后边它就像一个函数一样,有一个画括号,把它括起来,那一般情况就是如果。有这个E的话。
07:00
那我们可能就会做一些什么样的操作,Log,比如说比方说我们把error打印出来,那else呢,我们就conso.log。把result打印出来,所以其实很简单的一种写法就是这样,大家可以看一下这样一个结果。诶,这个结果好像我们没有把它对应的东西打印出来啊,他会做一个,就是一般情况可能会做这种,就是Jason的一个一个处理,对吧,把它做一个序列化Jason string,就是把我们的一个Jason对象要转成一个字符串的,就是Jason的格式来让大家方便显示出来,所以。我们在这里把它做一个。
08:00
好,我们看一下,这样大家就可以看到它返回的内容。大家看这个返回的内容,其实跟我们上面直接get block的时候返回的内容是一样。就本身它返回的是一个Jason对象。在这个对象我们把它做序列,就是做这个序列化之后呢,大家可以看到,其实我们解析出来之后,跟上面这一个对象格式完全一样,一开始是difficulty对吧,后面是extra data。啊,只不过它是顺着写在后面了,然后get limit,然后get used,哈西后面的blocks bloom,这这些,所以大家可以看到就是。整个的这一个调用过程,没有任何返回的内容,没有任何的区别,只不过由刚才的这种同步调用的方式变成了异步调用方式。好大,大家可能就会觉得有点奇怪,同步调用不是很方便吗?我们直接一敲它就返回一个值,返回一个内容,为什么还要有这样的一个异步调用呢?
09:11
大家觉得同步和异步他们的区别,或者说各自的优势在哪里?这这个大家之前。有这个心得吗?或者说有这个体会吗?通过他完善是。嗯,就是怎么说呢,就是那一个站的那个可以。就是你第,比如说第四行代码还有执行你下面的代码可以继续执行,嗯,对对,其实最主要的区别就是同步会阻塞对吧?对,同步会把当前的执行的这一段代码,执行的这个进程完全阻塞在这里,等我前面的这个调用拿到返回结果之后,后面的代码才会执行,所以呢,同步好的一点是它的顺序是有保证的,我们让谁先执行,谁就一定先执行,他完了之后才轮到后面的,但是不好的一点他就是也很明显。
10:12
它卡在这里可能我们就要等好久,所以大家可以看到,就是我们在开发外部应用的时候,其实一般情况是用异步的,那大家在前端用就是j query啊,发这个阿贾克斯请求什么的,都是异步的模式,因为我们知道在前端的时候,你直接把网页,直接把这个显示的页面给用户阻塞,就是你要发一个请求,然后你会发现他们服务器通信拿不到数据,这边什么都不显示,一个一片打空白,这当然是不能容忍的,对吧,这用户肯定是说我要拿什么数据,你你偷偷的去拿嘛,我这边该看别的我还得看啊。所以大家可以看到,就是一般在web应用,包括我们开发DAPP这些实例,实际应用的时候,往往都是要用异步的。
11:00
做异步调用的,所以在WEB3GS,它即使一开始它的设计目的是为了同步的应用,就是和本地通信啊,那同时它其实也是提供了异步调用的这种方式,可以发送异步请求的。而这个在之后1.0的版本里面就会体现的更为明显,到1.0版本之后呢,就是所有的调用其实都是一步了,呃,当然它就会封装的更加复杂一点,或者说更加规范一点,它所有的调用呢,会变成一个promise。大家之前学过promise学过是吧?对,而且他还是就是。更加包装之后的一个promise啊,等一下我们会就是应该有一页会详细的来讲这个1.0的一些动作啊,哦,就是这一页我们来跟大家说一下。
12:00
这其实就是为了适应我们后来越来越多的这种应用的情况,我们既然是要把它集成做这个DF。很有可能还会跟web开发相关,就跟整个的这个网页什么的都会交互起来,所以为了帮助WEB3集成道各种各样这种不同标准的所有类型的项目里面那1.0.0的版本,它就提供了多种方式来处理异步函数了,而且它的处理其实是更加通用化的,可以说在1.0.0里边就没有直接同步调用这么简单的方式了,基本上所有的东西大家都得用,就是都默认它的状态是一个异步的一个状态,那它是不是就没有办法保证顺序了呢?呃,大家来看一下,就是它是它是怎么做的啊,就是绝大多数的WEB3对象,它是允许将回调函数作为最后一个函数。呃,作为一个函数参数来传入的,这就是我们所说的呃,异步调用的时候加一个回调对吧?那同时它是会返回一个promise对象。
13:08
用于链式函数调用的。另外以太网作为一个区块链系统,它的一次请求其实是有可能有不同的结束阶段,这个是什么意思呢?就是比如说我们去发起一笔交易的时候。发起一笔交易的时候,首先我提交到一个节点那里,我们首先就会获得一个交易的哈希,对吧?这个哈希其实不是我们自己的程序或者我们自己的D能算出来的,这一定是以太坊节点告诉我们的,对,对不对,所以这其实就是我们跟以太坊节点第一次的交互,我们首先就会先拿到一个哈希。但是呢,拿到哈希并不代表这个交易就结束了呀,我们的交易只仅仅是发送出去而已,还没有打包镜框,还没有被确认,所以说之后肯定还会有一个打包镜块的一个事件出现,那这个时候我们如果跟以太网去交互,又会拿到一个东西。
14:12
在之后呢,它打包进块了之后,之后还会有区块再加到它后面来之后,那会相当于把它确认为,这是一个确认主面的过程,对吧?所以之后还会有确认事件,所以如果我们想确认一笔交易完全能够生效,完全已经成功,那其实我们是有这样不同的阶段,首先我们拿到哈希,然后我们确认他进了块,最后我们还要确认他确实是主链了,这已经就是一个一个的区块在他后面接上,又把它确认了。所以这其实是我们在以太坊上去发出一次请求的话,他可能是所谓的结束是有不同的阶段,那这样的阶段我们怎么样去分别的去检测到。
15:02
到了哪个阶段呢?出现了什么样的一个状态的变化呢?那为了解决这个问题,1.0.0版本,他就又把这个函数的返回值又包了一层,它包起来这个东西叫做pro event,就是可以翻译成就变成了一个承诺事件。就不光是一个promise,它是一个promise和一个event的一个结合体。所以大家可以看就是啊,就是标准的说的话,那就是GS里边有那个eventter的这个对象嘛,就是特别就是note里面,这是note里面的一个一个对象啊,Note里边的一个事件发生器这样的一个对象,所以以太网的1.0.0版本,把这两个东西结合起来之后。大家就会看到它的用法就会特别特别的奇葩,也不能说特别奇葩吧,大家如果熟悉这样的用法的话,就会觉得这个这个用法其实非常的舒服,非常的方便,大家看它怎么用,就是web3.e,呃,E点3TRANSCTION,这是发送一笔交易对吧?里边这是真正的发送的交易体,这就是from谁啊,但是它这个没有to啊,就是直接是data,那说明呃,这个看起来是像一个消息调用,那后面他这个交易发出去之后会怎么样呢?
16:25
他可以,除了他可以像promise promise,大家知道链式调用后面可以点赞对吧?对,就是可以拿到这个promise执行的结果,那除了它可以点赞之外,还可以加入点on.one.off等等方法,那这些方法是什么呢?这就是事件的方法对吧?就是去监听事件的方法,所以大家看它怎么用啊,就后面直接点once。然后transaction。后面跟一个回调函数。所以它就是说相当于在监听返回的交易哈希这个事件,对吧,一旦监听到返回有交易哈希这个事件,那我就执行后面的回调,而且这个是只执行一次,你不要每次都就是频繁的一直监监听对吧,那你哈希我其实是拿到一次,我就知道他已经成功了嘛。
17:21
之后呢,还可以点once receipt receipt是一个什么东西呢?Receipt是所谓的收据,那就是在我们的交易打包进块的时候。真正进入到区块里边的时候,就会收到这个收据。那就会触发这样一个事件,这是一次once就可以了。那再往之后呢,还可以点on on什么呢。Confirmation。也就是说之后有区块进来确认的时候,那我就再触发这个事件,我监听到了之后发现,哦,我这个不仅仅已经是打包进块了,而且后面又有了一个确认,那之后还会再有一个确认,再有一个确认,所以这其实这就是一个比较完整,比较可以说是比较完美的一个就是发送事件,然后监听它之后所有状态的一个过程,当然这是1.0.0版本里面的事件啊,我们现在如果要用0.2几的版本的话,那就还不能用这种方式。
18:26
我们用的方式可能就会比较原始一点,就是直接就只能是后面一个回调,然后回调里边我们直接拿到它的result,然后再去判断哦,它里边有什么什么样的状态,然后要想判断它真正的打包进块的话,我们还得另外的去做时间的监听,可能是这样的一个过程,那之后我们会带着大家实现,就是0.2级这个版本的啊,大家实现了那个之后,其实1.0.0,大家想要去转换,想要去切过去的话,应该是比较简单的。这里给大家多说一句,就是点赞的时候,大家可以看到后面它是function receipt。
19:05
所以后边的这个哦,有点到后面后边的这个re,呃,点赞里边这鼠标有点问题啊,点赞里边传入的这个回调函数,它的参数是什么呢?其实就是我们前面收到的这个收据receipt。所以点赞后面的这个回调什么时候出发。是。他在打包尽快收到收据的时候就出发。这里。所以大家就是如果以后用这个1.0.0的话,注意就是前面的这个promise它的。表示他完成这个异步回调完成的状,这个标志是什么呢?是收到receipt,也就是说交易打包镜框,这是我们需要注意的一个地方。好,接下来我们再看一下另外一个概念,就是前面我们已经提到过的一个东西叫API。
20:01
Abi全称是应用二进制接口,它是个什么东西呢?它其实是。WEB3,它通过以太坊的智能合约的这个接口就可以用用它来创建一个对应的JS对象。所以这个abi,这个相当于就是智能合约的一个Jason描述。或者说就是我们跟就是智能合约暴露出来的一个标准接口。我们通过这样的一个接口,就可以把智能合约转换成我们别的地方应用程序里面的对象实例,然后你就可以用它。要不然我们在我们的JS代码里面怎么去描述一个合约呢?我们仅仅是有地址肯定还是不行的,因为我们并不知道这个地址上它有什么什么样的操作,它有什么什么样的具体的行为,所以需要他把它里边的这种描述,它里边有什么样的函数,有什么样的,有什么样的变量,有什么样的事件,把这些东西告诉我,所以整个的这种Jason描述就叫做API,这就是我们所说的应用二进制接口。
21:15
它里面主要包含的就是这两类,一个是函数,一个是事件,就是functions和events。那functions里边它会有很多很多的属性。或者说它有很多很多的字段,其中比较重要的一个是type,这是表明函数类型。那默认的这个type就就叫function式,Type的值就是function,那也可能是constructor了,就假如这是我们的这个构造函数的话,那它就是一个constructor,另外就是还有可能是for back,当然还有可能那个我们的回推函数,对吧,但是目前在那个WEB3里面,它对for APP是没有这种专门的处理和这种就是直接调用的这种方式的,所以说我们在WEB3里面见不到啊,后面还有几样就是constant payable state,呃,Muability这几样描述的函数的状态可变性,就是说它是不是可支付的呀,它是不是可以去写呀,是不是可以去读啊,就我们介绍的那几样对吧,就是它是。
22:21
它是view类型的,还是还是PE类型的,还是peable类型的,就是这几这几个关键词,最后还有就是input outputs,这是输入输入输出的参数列表啊,这个在这里很宽泛的,这么一说大家可能觉得这个很枯燥啊,那我们接下来我们就真正的来看一看它这个API到底是什么东西,好,那我们现在大家打开我们的命令行。这是我们的盖好,我们到命令行里边来,呃,大家还有之前写好的这个合约吗?
23:08
大家可以把之前的某一个合约可以copy过来啊,我这里就可以,比方说我比较简单的去啊,这里看不清楚了是吧,我把这个放到这里来看啊好,我在这边的操作,呃,我们首先先创建一个合约吧。因为这个。呃,比方说我们这个就就拿我们之前那个号这个合约来来做我们这个例子吧,我就不手抄了,我们之前应该是写过这个的,对吧。把它复制过来,因为我们这节课不是主要内容,不是来写合约的啊,这个都已经很熟悉了,我们看一下它内容,这是我们当时写好的这个coin,最简单的这个子货币。
24:04
这个合约已经放在这里了,我们看到啊,Coin,呃,我们还是把它放到一个文件夹下面吧。我们把放到下面去好。好,现在我们到了这里来,我们准备把它做一个编译。怎么样去编译它呢?其实非常简单,只要大家已经装好了sock,呃,但是大家操这个命令可能是SOSOJS对吧,我们编译这一个Co原文件,只要给它传入这么几个参数啊,大家看,我就输入了一个杠杠abi,对吧,这样吧,我先不敲前面的这个,我们就看看这个API好了,杠杠API,然后后面跟上我们的原文件名字。
25:03
大家可以看一下。好,他应该已经编译完成,编译完成之后,大家就能看到在当前的目录下生成了一个。Co so co.abi,那我们可以打开这个A文件,看看它到底是个什么东西。大家能看到是吧。它里边是些什么样的东西呢?啊,我们这个好像有点看不太清楚啊,我把它复制出来,我们。我们另外把它写一下。上和刚才我们那个外三代都已装上了吗?都装上了是吧?好,那大家可以先把它试着先做一下编译,编译完了之后我们来一起解析一下,这个就是API文件,看一下它里边的内容。
我来说两句