什么是链式调用?
对于用过jq的人来说这个概念很好理解,例如:
$('text').setStyle('color', 'red').show();
其中调用过setStyle方法后可以立即再调用show方法。这要的调用方式就是链式调用。
链式调用是如何实现的?
一般的链式调用完方法后,return this返回当前调用方法的对象就能实现链式调用。
首先,我们先来看看一般函数的调用方式
(1)先创建一个简单的类
//创建一个bird类 function Bird(name) { this.name=name; this.run=function() { console.log(name, "start run;"); } this.stopRun=function() { console.log(name, "start run;"); } this.sing=function() { console.log(name, "start sing;"); } this.stopSing=function() { console.log(name, "start stopSing;"); } }
(2)使用方式:一般的调用方式
var bird=new Bird("测试"); bird.run(); bird.sing(); bird.stopSing(); bird.stopRun();
(3)结果
测试 start run; 测试 start sing; 测试 start stopSing; 测试 start run;
总结,该种方式有一个弊端就是:多次重复使用一个对象变量
然后,我们再来看看将上述改成链式调用的格式
(1)在创建的简单类中加上return this,如下
//创建一个bird类 function Bird(name) { this.name=name; this.run=function() { console.log(name, "start run;"); return this;// return this返回当前调用方法的对象。 } this.stopRun=function() { console.log(name, "start run;"); return this;// return this返回当前调用方法的对象。 } this.sing=function() { console.log(name, "start sing;"); return this;// return this返回当前调用方法的对象。 } this.stopSing=function() { console.log(name, "start stopSing;"); return this;// return this返回当前调用方法的对象。 } }
(2)使用链式调用(连缀的方式)
var bird=new Bird("测试"); bird.run().sing().stopSing().stopRun();
(3)结果
测试 start run; 测试 start sing; 测试 start stopSing; 测试 start run;
总结此种方式的调用结果与一般的调用方式产生的结果一样,优点是:链式调用这种风格有助于简化代码的编写工作,让代码更加简洁、易读,同时也避免多次重复使用一个对象变量
Promise链式调用
什么是promise的链式调用呢
// 省市区 function printProvince() { return new Promise((resolve, reject) => { setTimeout(() => { console.log('省'); resolve(); }, 100); }); } function printCity() { return new Promise((resolve, reject) => { setTimeout(() => { console.log('市'); resolve(); }, 100); }); } function printArea() { return new Promise((resolve, reject) => { setTimeout(() => { console.log('区'); resolve(); }, 100); }); } printProvince().then(() => { return printCity(); }).then(() => { return printArea(); }).then(() => { console.log('打印完成'); });
结果
省 市 区 打印完成
Promise链式调用升级版
上边的链式调用已经简化了一些代码,逻辑也比较清晰,但是在遇见大数据量的处理时then就要写好长好长,有没有好的方法能实现代码动态控制自动完成的情况呢?
const createPromise = (name) => () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name); resolve(); }, 100); }); } const phones = ['华为', '小米', 'OPPO', '金立', '荣耀']; const allP = []; phones.forEach((phone) => { allP.push(createPromise(phone)); }); allP.reduce((prev, next) => prev.then(() => next()), Promise.resolve()).then(() => { console.log('执行完成'); });
执行结果:
华为 小米 OPPO 金立 荣耀 执行完成
这样就可以动态生产一个链式调用的过程了。相比于上边的手动写链式调用要代码量少好多。
总结
有人说这个和Promise.all有点像,但是也有区别。
(1)链式调用是串行调用,一个promise执行完成后才调用下一个promise;Promise.all是并行执行,其中的promise没有先后顺序,有计算机随机调用。
(2)链式调用执行时间会长,但是占用的计算机资源少;Promise.all 执行时间相比链式调用短,但是占用的计算机资源多。