同步执行就是要等待上一个表达式执行完成,返回结果后再继续执行下一个表达式,即使是耗时的异步函数(网络请求/数据库操作)也会同步执行,好像马上就能拿到结果一样,这样每个表达式都可以得到上一个表达式的执行结果$r
。同步执行是单线程运行,就像过独木桥,等你过完桥了我再过。
在众触事件逻辑中几乎所有表达式都是同步执行(按顺序执行)的,即一条表达执行完毕才会开始执行下一条,即使是耗时的操作也如此。同步执行保证了下一条表达式执行的时候上一条表达式已经执行完毕,也就能知道上一条表达式的执行结果。比如:
$product.find({})
$v.商品s = $r.arr
执行第二行的时候第一行的表达式已经完成,用$r来表示上一行表达式的返回值(数据库搜索结果)。通常这么写更简洁:
$v.商品s = $product.find({}).arr
本来数据库查询就是个耗时的工作,要花一段时间才能拿到返回值的,但使用起来好像马上就能拿到值一样。这样符合人类的直觉,使用简单,减少心智负担。
异步执行就是不等待上一条表达式的执行结果,马上执行下一条表达式,所以无法获取异步函数的返回值。异步执行是多线程同时运行,互不等待,互不干扰,互不依赖。就像有多条桥,你过你的桥我过我的桥,虽然我晚过桥但我可能比你还先过完桥。
同步执行虽好,但也不是没有缺点的,它的优点有时候就会成为缺点。
如果用于页面展示的表达式同步执行的话,碰到耗时的网络请求就会造成页面卡顿,所以用于页面展示的小括号中的表达式都是异步执行的,我们希望它们快速完成,马上展示给用户看。
如果一个事件中有多个网络请求,它们直接互相不依赖,如果同步执行的话就会一个网络请求完成后再执行下一个请求,花费比较多的时间。如果异步执行就会把多个请求一起发送出去,各自执行各自的,互不相干,互不等待,就能提高整体执行效率,降低所消耗的时间。
有个场景是load()了个外部JS库,如果这个JS库是用then来接受调用结果的的异步函数,那就只能把这个调用过程放到异步函数excA()里执行了,因为众触内部的同步执行是用await,返回的是一个承诺(Promise)。
只有3个异步函数:excA()
、 fxA()
、 forEachA()
。放在里面的表达式将异步执行,它们后面的表达式不能获取里面表达式的执行结果。
都有对应的同步函数(函数名没有A
)。