setTimeout方法中的一个小坑

梭罗说:“我到林中去,因为我希望用力地生活,只面对生活最纯粹的真相,看看我是否领悟其真谛,免得到了临死之时,才发现自己根本没有活过……”

梭罗不是程序猿,但梭罗给程序猿也是有启示的:有些坑,只有你奋不顾身的跳进去,你才会彻悟那些代码的真相,否则到了临死之时,才发现自己根本没写过啥像样的程序……

自从摸过nodejs之后,自然是要被多重嵌套的回调函数虐的。据说COMMONJS给出了一个名叫Promise的规范,之后许多js的库都推出了promise的编程模式来方便编写异步调用的代码。对于初级的程序猿来说,这些抽象的模式,理解起来是最容易摸不着头脑的。当然笨人自然有笨人的办法,就像阿甘说的那样:stupid is as stupid does!笨人就做笨事吧——对着网络上搜索来的最简单的案例代码,一点点自己敲出来,四处console.log一下。然后,就会发现很多坑,而且这些坑可能并不是来自当前这个新东西,而是自己既有的一些基础知识不牢固。

function asyncFunction() { 

            return new Promise(function (resolve, reject) {        

                setTimeout(function () {            

                    resolve('Async Hello world');        

            }, 16);    

        });

}



asyncFunction().then(function (value) {

    console.log(value);    // => 'Async Hello world'

}).catch(function (error) {

    console.log(error);

});

上面这段带码是直接从某个网站复制过来的,运行了一下,乍一看没发现什么坑。然而当我把代码改成这样,自己就给自己造了一个坑。

var Q=require('q');

var start=(new Date()).getTime();

var asyncP=function(){

    return new Promise(function(resolve,reject){

        setTimeout(resolve(34) ,500);

        console.log('start at '+start)

    })

}



function onfullfilled(v){

    console.log('--'+v);

    console.log('now the time span is '+((new Date()).getTime()-start));

    return v+10;

}



asyncP().then(onfullfilled).then(onfullfilled).then(onfullfilled);

执行结果是这样的:

setTimeout方法中的一个小坑_第1张图片

说好的500毫秒执行一次的那句“setTimeout(resolve(34) ,500);”怎么没有生效?看看打印的结果:the time span is xxxxx,没有一个是超过500毫秒的。这说明这个异步执行有大大的问题。类似的问题我之前遇到过,至今并没有找到一个合适的解释,只是自我总结为:setTimeout(func, timespan)这个方法中,func如果写作一个函数名则不能带参数,如果要需要带参数,只能写作一个匿名函数,然后在函数体内再写被引用的函数和参数,否则被引用的函数不会等到timespan之后才执行,而是立刻就执行了。下面的对比代码会看出差别来。

栗子A:

var start=(new Date()).getTime();

console.log('start at '+start)

setTimeout(test(3),1000);

function test(v){

    console.log('test');

    console.log('now the time span is '+((new Date()).getTime()-start));

}

执行结果是:

这里写图片描述

栗子B:

var start=(new Date()).getTime();

console.log('start at '+start)

setTimeout(test,1000);

function test(){

    console.log('test');

    console.log('now the time span is '+((new Date()).getTime()-start));

}

执行结果是:

这里写图片描述

栗子A和栗子B的唯一差别就是setTimeout时,一个写的是test,一个写的是test(3)。行文至此,我突然明白了,按照setTimeout的方法定义,第一个参数是function,而不是function执行的结果。所以栗子A中,setTimeout得到的第一个参数其实是undefined——因为test方法的执行结果没有返回任何东西。

原来如此,这么一个坑,差点让我以为前面找来的promise的简单实现代码是不可用的。写一写还是大大有好处的,不管你写的是代码还是文字。就算自己写给自己看,还是会让自己看见一些不一样的东西

你可能感兴趣的:(javascript)