Promise结合reduce构建顺序执行队列

    Promise是一个解决函数异步执行的对象,有了这个对象,我们可以构造异步执行的操作。Promise对象可以通过链式调用的方式进行异步操作,语法如下:

    

    如下代码,是一个简单的异步方法。

new Promise((resolve,reject)=>{
	console.log("promise-> hello,world.this is promise. "+new Date());
	setTimeout(()=>{
		resolve("hello,world.this is promise. "+new Date());
	},1000);
}).then((value)=>{
	console.log("then   -> "+value);
});

    运行这段代码,得到结果如下所示:

     

    通过Proimse我们很好的构建了一个异步操作,then中的函数始终都会在resolve()执行之后才开始执行。resolve()可以携带参数,这个参数到了then里面,就可以通过回调函数中的参数获取了,如题所示的value值,就是通过resolve(args)传递过来的。 

    另外,这里还有一个reject函数,就是当Promise内部执行出现异常,我们才会调用。这时候,一般then是不会执行的,这里如果要在reject后,继续执行then中的内容,我们需要在then中增加一个reject的函数处理。

new Promise((resolve,reject)=>{
	console.log("promise-> hello,world.this is promise. "+new Date());
	setTimeout(()=>{
		reject("hello,world.this is promise. "+new Date());
	},1000);
}).then((value)=>{
	console.log("resolve-> "+value);
},(value)=>{
	console.log("reject -> "+value);
});

    执行结果如下:

     

    一般情况下,为了简单,Promise只用来做异步处理,我们都不处理reject的情况,所以Promise写起来会很简单。比如:

new Promise(resolve=>{
	console.log("promise-> hello,world.this is promise. "+new Date());
	setTimeout(()=>{
		resolve("hello,world.this is promise. "+new Date());
	},1000);
}).then(value=>{
	console.log("resolve-> "+value);
});

    以上示例,从直观上感受到了Promise的强大,我们再也不用通过函数嵌套回调的方式来做异步操作了。如下所示的异步回调方法,一层套一层:

setTimeout(function(){
    //todo
    setTimeout(function(){
        //todo
        setTimeout(function(){
            //todo
        },1000);
    },1000);
},1000);

    嵌套回调,容易造成callback hell,Promise的then中,可以继续返回新的Promise,这样,可以构建一个简单的异步回调。而且写法更直观,更易于理解:

new Promise(resolve=>{
	console.log("promise 1");
	setTimeout(()=>{
		resolve();
	},1000);
}).then(()=>{
	return new Promise(resolve=>{
		console.log("promise 2");
		setTimeout(()=>{
			resolve();
		},1000);
	});
}).then(()=>{
	return new Promise(resolve=>{
		console.log("promise 3");
		setTimeout(()=>{
			resolve();
		},1000);
	});
});

    Promise除了以上的用法,还可以有Promise.all().then()的用法,all()表示所有的操作均执行完成,再执行then()中的方法。而all()中的函数,不是顺序执行,而是同时执行。

const createPromise = (id) => 
	new Promise(resolve=>
		setTimeout(()=>{
			console.log("promise->"+id+":"+new Date());
			resolve();
		},1000)
	)
var tasks = [createPromise(1),createPromise(2),createPromise(3)];
console.log(tasks);
Promise.all(tasks).then(()=>console.log("all done."));

    运行结果:

     

    从运行结果看来,他们几乎是同一时刻,这种异步,虽然最终都会全部执行完成,再执行then()中的代码,但是all()中的函数并没有顺序执行。如果希望then()之前的函数都是顺序执行的,可以考虑通过reduce函数来实现。这里会比较难以理解。

const createPromise = (id) => () => 
	new Promise(resolve=>
		setTimeout(()=>{
			console.log("promise->"+id+":"+new Date());
			resolve();
		},1000)
	)
var tasks = [createPromise(1),createPromise(2),createPromise(3)];
console.log(tasks);
var doTask = tasks.reduce((prev,next)=>prev.then(()=>next()),Promise.resolve());
doTask.then(()=>console.log("all done."));

    这里需要注意的是,我们的createPromise函数,不再返回的是Promise对象,而是一个函数,函数里面再返回Promise对象。运行我们的代码,截图如下:

     

    可以看到,这里三个函数是按照顺序执行的,并没有同时执行,等到全部执行完成,最后执行then()中的方法。其实这种reduce写法,就回到了我们前面提到的Promise().then().then().then()的写法, 只不过使用reduce代码更简洁了,我们需要注意的是reduce()的数组是一个Function的数组,而不是Promise的数组。另外,reduce()方法的第二个参数,他是一个初始值,在这里就是Promise.resolve(),他表示一个动作已经执行完成,可以进行下一个动作了。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值