Promise中setTimeout两种写法的行为差异原因咨询
嘿,我来帮你拆解下这个setTimeout行为差异的问题~
setTimeout的第一个参数要求是一个函数引用,而非函数执行后的结果。咱们结合你的代码逐个分析:
场景1:为什么会等待5秒?
看这段代码:
module.exports.addNumbers = function(numberArray){ return new Promise(function(fullfil, reject){ setTimeout(() => { if(!(typeof numberArray === 'Array')) reject('Not number elements found!'); },5000); }); }
你传给setTimeout的是一个箭头函数(匿名函数),这是一个真正的函数引用——JavaScript会把这个函数“存起来”,等5秒超时时间到了才会执行里面的逻辑,所以Promise会一直处于pending状态,直到5秒后才触发reject,对应你看到的“响应需等待5秒”。
场景2:为什么会立即resolve/reject?
再看场景2的关键代码:
module.exports.addNumbers = function(numberArray){ return new Promise(function(fullfil, reject){ setTimeout(add(numberArray, fullfil, reject),5000); }); } function add(numberArray, fullfil, reject){ if(!(typeof numberArray === 'Array')) reject('Not number elements found!'); }
问题出在setTimeout(add(numberArray, fullfil, reject),5000)这一行:你直接写了add(...),这会立刻执行add函数,而不是把add作为回调函数传给setTimeout。
当JavaScript执行到这行时,会先计算add(numberArray, fullfil, reject)——也就是马上调用add函数,里面的reject语句会立刻触发,Promise直接进入rejected状态,所以你的请求会瞬间得到响应,完全不等那5秒的超时。
要让场景2和场景1一样延迟执行,你需要把add函数包装成一个“待执行的引用”,有两种常用方式:
方法1:用匿名函数包装
setTimeout(() => add(numberArray, fullfil, reject), 5000);
这样传给setTimeout的是一个箭头函数引用,5秒后才会执行这个箭头函数,进而调用add。
方法2:使用bind绑定参数
setTimeout(add.bind(null, numberArray, fullfil, reject), 5000);
bind会返回一个新的函数引用,这个函数在被调用时会带着你指定的参数执行add,同样会等待5秒才触发逻辑。
你的代码里判断数组的方式有误:typeof numberArray === 'Array'是错的,因为typeof检测数组返回的是'object'。正确的判断方式应该是:
// 推荐方式:Array.isArray if(!Array.isArray(numberArray)) reject('Not an array!'); // 备选方式:instanceof if(!(numberArray instanceof Array)) reject('Not an array!');
内容的提问来源于stack exchange,提问作者Saumya Ranjan Satapathy

