seTtimeout和promise都是跟异步编程有关,我们先来看看setTimeout的用法。
setTimeout设置一个函数延时执行,test.js如下代码:
function second()
{
console.log('second');
}
setTimeout(second,5000);
console.log('first');
我们编写了一个second函数,输出second.
在setTimeout设置这个函数5秒后执行。所以执行顺序如下:
需要注意的是javascript是单线程语言,所以不可能有真正意义上的同时执行两件事,两个线程同时工作那种情况。
所以看下面代码:
//自定义的睡眠函数
function sleep(ms) {
let start = Date.now()
let end = start + ms
while(true) {
if(Date.now() > end) {
return
}
}
}
function second()
{
console.log('second');
}
setTimeout(second,1000);
sleep(2000);
console.log('i am first');
还是先输出的first,而不是说1秒后就执行了second。
像前面我们的second函数没有参数,如果有参数是怎么调用的呢,如下:
setTimeout一种传递参数的方法
function second(i)
{
console.log('second'+i);
}
setTimeout(second,1000,33);
console.log('first');
输出结果:
参数写在setTimeout第三个参数里就可以了,如果是多个,后面依次增加即可。
setTimeout调用函数的一种写法。像之前我们单独定义了second函数来调用,其实也可以这样简写的如下:
setTimeout(function(){
console.log('second')
},1000);
console.log('first');
直接在setTimeout里定义。
如果有参数是这样:
setTimeout(function(i){
console.log('second'+i)
},1000,33);
console.log('first');
还可以用=>这样简写,去掉了function
setTimeout((i)=>{
console.log('second'+i)
},1000,33);
console.log('first');
Promise对象
promise是一个对象,我个人理解是promise是用来控制异步函数的顺序,工作流程的。像前面我们只有一个setTimeout,不需要promise,但是如果有多个setTimeout异步任务呢。
我们又或者需要某个异步完成,再执行某个功能。这里面肯定不是杂乱无章的,我们需要一种方法帮我们可以很好的控制这些异步的执行顺序和条件。所以我们通过promise来实现控制。
如何创造promise
通过new Promise()构造函数的方式,并且构造函数需要有一个参数,这个参数是个函数并且带有两个参数(resolve,reject),如下代码创造:
function pc(resolve, reject){
console.log('hello');
}
var prom1=new Promise(pc);
因为是构造函数,所以在new的时候,构造函数代码立即被执行。
那么运行后结果如下:
在前面的pc函数中,有两个参数,resolve和reject,这个传递的是两个函数,调用这两个函数,可以改变你创建的这个promise状态,promise有三种状态,Pending(未完成),Resolved(已完成)和Rejected(已失败)
为什么需要这三个状态,因为我们创建一个异步任务,我们不知道什么时候成功或失败。
我们需要传递消息,通过更改promise的状态来达到目的。
那么在promise里调用resolve函数,则表明已完成,调用reject函数,则表明失败。
在哪里接收或者说处理这些状态----then函数
promise的then函数,可以帮我们添加相应状态的处理函数,then函数的第一个参数就是处理成功时函数,第二个参数是处理失败时候的函数(第二个参数看情况可不写忽略),应用代码如下:
//pc为promise构造函数的参数
function pc(resolve, reject){
console.log('hello');
resolve('执行成功');
}
//rs为响应resolve状态的处理函数
function rs(rsdata){
console.log('rs:'+rsdata);
}
var prom1=new Promise(pc);
prom1.then(rs);
执行结果:
注意这里我只是做说明使用,并没有处理逻辑,所以只写了部分,关于resolve函数,我传递一个字符串,事实上也可以传递一个变量对象什么的,而在rs函数的rsdata就接收了这个传递过来的参数。
这句,prom1.then(rs) 调用rs函数,它跟setTimeout一样,都可以指定一个回调函数,不是立即执行的,只不过一个根据时间,一个是根据resolve。
所以下面的代码:
//pc为promise构造函数的参数
function pc(resolve, reject){
console.log('hello');
resolve('执行成功');
}
//rs为响应resolve状态的处理函数
function rs(rsdata){
console.log('rs:'+rsdata);
}
var prom1=new Promise(pc);
prom1.then(rs);
console.log("first");
顺序如下:
PS:在这里,你们可以把函数也当成一个变量那样传递看待,那么一切就不会变得奇怪,比如函数随便变换名字,就像变量一样a赋给b或者,函数的一个变量参数,在函数里又变成另一个名字,但它们的值都是不变的。这些跟回调函数有关,而在node中大量使用了回调函数。
比如像这样:
var fn = function(callback)
{
var str='hello'
callback(str);
};
fn(function(s){
console.log(s);
});
运行结果:
能看懂上面代码的流程和关系吗?上面先定义一个fn函数,它的参数是需要一个函数。
那么我在调用fn时,是直接在fn里定义了这个函数(没有单独写一个再传进去,后面为了简便都将采用此种写法了,就像我们的字符串变量,然后我调用时直接'执行成功‘这样传递,一样的道理)
多个then的使用
调用then方法时,又会返回一个新的promise对象,那么它又有一个then方法。并且接收的是return的值。如下:
//pc为promise构造函数的参数
function pc(resolve, reject){
console.log('hello');
resolve('执行成功');
}
//rs为响应resolve状态的处理函数
function rs(rsdata){
console.log('rs:'+rsdata);
return '第二个then'
}
var prom1=new Promise(pc);
prom1.then(rs).then(i=>{
console.log('rs2:'+i);
});
第二个then就是当第一个then关联的函数执行完后就会调用里面的函数,参数是通过return传递的。它们的顺序逻辑就是这样的,结果如下: