ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

JavaScript专项算法题(4):异步

JavaScript专项算法题(4):异步

>>> ORIGIN全文地址:JavaScript专项算法题(4):异步

推荐:编程鼠标·电竞鼠标

异步

挑战一 sayHowdy

问题:

思考时间(现在暂时不需要编写代码):分析下方挑战一的代码,打印出来的结果会是怎样顺序的?Howdy先还是Partnah先?

题解:

/* CHALLENGE 1 */functionsayHowdy(){console.log('Howdy');}functiontestMe(){setTimeout(sayHowdy,0);console.log('Partnah');}// After thinking it through, uncomment the following line to check your guess!// testMe(); // what order should these log out? Howdy or Partnah first?

挑战二 delayedGreet

问题:

构建delayedGreet函数,用于在3秒后打印“welcome"。

题解:

/* CHALLENGE 2 */functiondelayedGreet(){// ADD CODE HEREsetTimeout(()=>console.log('welcome'),3000);}// Uncomment the following line to check your work!// delayedGreet(); // should log (after 3 seconds): welcome

挑战三 helloGoodbye

问题:

构建helloGoodbye函数。其会立刻打印”hello",然后2秒后打印“good bye"。

代码:

/* CHALLENGE 3 */functionhelloGoodbye(){// ADD CODE HEREsetTimeout(()=>console.log('good bye'),2000);console.log('hello');}// Uncomment the following line to check your work!// helloGoodbye(); // should log: hello // should also log (after 3 seconds): good bye

挑战四 brokenRecord

问题:

构建brokenRecord函数。其会每秒钟都打印一次”hi again“。使用”End Code“按钮结束打印如果你对代码的运行满意的话。(译注:原题库网页上的按钮)

题解:

/* CHALLENGE 4 */functionbrokenRecord(){// ADD CODE HEREsetInterval(()=>console.log('hi again'),1000);}// Uncomment the following line to check your work!// brokenRecord(); // should log (every second): hi again

挑战五 limitedRepeat

问题:

构建limitedRepeat函数。其会每秒钟打印一次”hi for now",但仅仅持续5秒钟。如果你感到困难的话,研究clearInterval。

题解:

/* CHALLENGE 5 */functionlimitedRepeat(){// ADD CODE HEREconstintervalId=setInterval(()=>console.log('hi for now'),1000);setTimeout(()=>clearInterval(intervalId),5000);}// Uncomment the following line to check your work!// limitedRepeat(); // should log (every second, for 5 seconds): hi for now

挑战六 everyXsecsForYsecs

问题:

构建everyXsecsForYsecs函数。其接受三个参数:一个函数func、一个数字interval和另外一个数duration。

everyXsecsForYsecs函数会以interval秒的间隔运行函数func,但会在duration秒后结束运行。

题解:

/* CHALLENGE 6 */functioneveryXsecsForYsecs(func,interval,duration){// ADD CODE HEREconstintervalId=setInterval(func,interval*1000);setTimeout(()=>clearInterval(intervalId),duration*1000);}// Uncomment the following lines to check your work!functiontheEnd(){console.log('This is the end!');}everyXsecsForYsecs(theEnd,2,20);// should invoke theEnd function every 2 seconds, for 20 seconds): This is the end!

挑战七 delayCounter

问题:

构建delayCounter函数,接受的第一个参数为一个数组(称为target),第二个参数为毫秒单位的数字(称为wait),返回结果为一个函数。

当返回函数被调用时,它会依序打印从1到target之间的数字(含target),以wait毫秒的时间间隔。

题解:

/* CHALLENGE 7 */functiondelayCounter(target,wait){// Solution 1:letintervalId;letcounter=0;returnfunctioninner(){if(counter===0){counter++;intervalId=setInterval(()=>console.log(inner()),wait);}elseif(counter===target){clearInterval(intervalId);returncounter;}else{returncounter++;}}// Solution 2://return function inner() {// for(let i = 1; i<=target; i++){// setTimeout(()=>console.log(i), wait * i);// }//}}// UNCOMMENT THESE TO TEST YOUR WORK!// const countLogger = delayCounter(3, 1000)// countLogger();// After 1 second, log 1// After 2 seconds, log 2// After 3 seconds, log 3

挑战八 promised

问题:

构建promised函数,接受一个值作为参数。它会返回一个在两秒后触发resolve函数的Promise对象。

提示:到MDN去查阅下Promise对象的文档。

题解:

/* CHALLENGE 8 */functionpromised(val){// ADD CODE HEREconstpromiseObj=newPromise((resolve)=>{setTimeout(()=>resolve(val),2000);});returnpromiseObj;}// UNCOMMENT THESE TO TEST YOUR WORK!// const createPromise = promised('wait for it...');// createPromise.then((val) => console.log(val));// will log "wait for it..." to the console after 2 seconds

挑战九 SecondClock

问题:

编写一个SecondClock类。其有两个方法:start和reset。

start:当调用时,start会每秒调用一个回调函数(this.cb,在构造器中定义),作用于一个变量。这个变量每次被回调函数使用时总是当前的时间秒数。

换言之,此回调函数每一秒钟都基于时钟信号的秒数而被调用,总是从1开始但并不使用当前计算机上的时钟信号的秒数值。

第一次“滴答”(值为1)发生在最初的secondClock调用的1秒后;

第二次“滴答”(值为2)发生在最初的secondClock调用的2秒后;

……

第六十次“滴答”(值为60)发生在最初的secondClock调用的60秒后;

第六十一次“滴答”(值为61)发生在最初的secondClock调用的61秒后;

第六十二次“滴答”(值为62)发生在最初的secondClock调用的62秒后;

以此类推。

reset:当调用时,完全停止SecondClock时钟的运行,另外重设时间为初始值。

提示:查阅setInterval和clearInterval。

题解:

/* CHALLENGE 9 */classSecondClock{constructor(cb){// ADD CODE HEREthis.counter=0this.intervalId=0this.cb=cb}// ADD METHODS HEREstart(){this.intervalId=setInterval(()=>this.cb(++this.counter),1000);}reset(){clearInterval(this.intervalId);this.counter=0;this.intervalId=0;}}// UNCOMMENT THESE TO TEST YOUR WORK!// const clock = new SecondClock((val) => { console.log(val) });// console.log("Started Clock.");// clock.start();// setTimeout(() => {// clock.reset();// console.log("Stopped Clock after 6 seconds.");// }, 6000);

挑战十 debounce

问题:

构建debounce函数,接受参数为一个回调函数callback和一个数值interval,返回结果为一个函数。此返回函数仅会在其上次调用回调函数的interval毫秒后才会被再次调用回调函数。

在interval毫秒时间内调用返回函数不会被响应或列入队列,然而时间信息会被重置( 译注:interval时间重新开始计算)。

有关防抖函数的例子:请查看这个链接 https://css-tricks.com/debouncing-throttling-explained-examples/

题解:

/* CHALLENGE 10 */functiondebounce(callback,interval){// ADD CODE HERE// Solution 1:lettimeCounter=0lettimeoutId=nullreturnfunction(){if(timeCounter===0){timeoutId=setTimeout(()=>{timeoutId=null;timeCounter=0;},interval);timeCounter++;returncallback();}else{if(timeoutId){clearTimeout(timeoutId);timeoutId=setTimeout(()=>{timeoutId=null;timeCounter=0;},interval);timeCounter++;}else{timeCounter++;returncallback();}}}// // Solution 2 (Not efficient):// return function (){// if (timeoutId) {// clearTimeout(timeoutId);// timeoutId = setTimeout(() => timeoutId = null, interval);// } else {// timeoutId = setTimeout(() => timeoutId = null, interval);// return callback();// }// }}// UNCOMMENT THESE TO TEST YOUR WORK!functiongiveHi(){return'hi';}constgiveHiSometimes=debounce(giveHi,3000);console.log(giveHiSometimes());// -> 'hi'setTimeout(function(){console.log(giveHiSometimes());},2000);// -> undefinedsetTimeout(function(){console.log(giveHiSometimes());},4000);// -> undefinedsetTimeout(function(){console.log(giveHiSometimes());},8000);// -> 'hi'

题库原地址:http://csbin.io/async

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进