疑问: js有sleep()吗?

settimeout

  • settimeout添加的事件, 会在下一次event loop执行, 问题出现了,
  • 我的代码里面5000*5000的循环, 然后如果循环内部的settimeout, 也就是要在5000X5000之后执行, 问题严重了. 这个一定是有问题的.
  • 因此, settimeout对我的这个场景无用.

settimeout小技巧: 传递参数

settimeout的第一个参数是一个function, js的规则function作为指针传递的时候, 都是不能指定参数的, 参数是由外部调用指定的, 在这个例子中, 如果这个function有参数, 也是settimeout自动指定的. 因此, 要传递参数, 需要一点小技巧, 两个写法都可以.

//包在外边
setTimeout(
  function(){
    httppre(json[i].stationName, json[j].stationName, '2017-12-16')//这里写多少的参数都可以.
  },   1000			
)

//包在里面
function fun2(objectP){
    return function(){
        // 这里开始干正事, 那个参数ObjectP都可以用了.
    }
}
setTimeout(fun2(p), 100);

//如果是字符串作为参数, 可以不那么麻烦, 问题来了, 多个参数咋办?
setTimeout("fun1('" + paramenter + "')", 100);
//这种形式不是太好, 因为其实是一个eval

//更完美的解决方案: Function.prototype.bind()
setTimeout(函数名.bind(null, topicId), 4000);
第一个参数, 可以传递一个函数指针(比如this)进去, 他指明了this的指向.

//第三个参数可以作为第一个参数(函数)的参数
setTimeout(alert, 1000, hello);
setTimeout(yourFunctionReference, 4000, param1, param2, paramN);

//匿名函数也可以直接带参数, 但是这种写法会导致括号套括号, 这个写法和前面的[第三个参数]其实是一样的.
setTimeout(function(参数) { //做点啥
}, i++ * 1000, 参数);

setTimeout(() => console.log(testObject[propertyName]), i++ * 1000);

//还可以用apply解决, 有兴趣的可以去研究下.

比如定时保存, 不论是ajax还是file本地保存

我们的策略都是一段时间没有保存, 才保存他, 而不是过于频繁的保存.
因此, 当用户敲击键盘我们就设置一个timeout保存, 然后, 用户再次敲击, 我们发现间隔很短, 就把之前的保存取消掉. 比如4s钟之内的.

function debounce(fn, delay){
  var timer = null; // 声明计时器
  return function(){
    var context = this;
    var args = arguments;
    clearTimeout(timer);
    //由于timer声明在外边, 因此对于匿名函数而言, timer一直记录了之前的一个, 所以, 每次只要简单的取消前面一个timer就好了, 完全不必写任何的判断.
    timer = setTimeout(function(){
      fn.apply(context, args);
    }, delay);
  };
}
// 用法示例
var todoChanges = debounce(batchLog, 1000);
Object.observe(models.todo, todoChanges);

没事就用settimeout是不合理的, 因为他有附加的cpu开销. js其实是单进程轮询机制, 轮询的内容越多, 轮询的效率必然越差.
这个blog写的比我的好, 本文大量参考/引用: https://jeffjade.com/2016/01/10/2016-01-10-javacript-setTimeout/

sleep的几种写法

//promise写法
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two second later');
}
demo();

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});

//玩命死循环判断时间的sleep是搞笑呢, 他完全堵塞了进程. 甚至于假死了整个computer.
//所以可以转变思路, 在需要timeout的地方, 控制timeout的间隔, 达到sleep的效果.

关于pormise的解释

//很不爽, 要用promise, 需要先创建Pormise对象, 如果这个对象是返回值. 那么那他就可以链式了.
new Promise( function(resolve, reject) {...} /* executor */  );
resolve和reject分别是两个函数. 对应于匿名函数执行状态(成功/失败).

//他替代了这种写法:
function successCallback(result) {
  console.log("It succeeded with " + result);
}
function failureCallback(error) {
  console.log("It failed with " + error);
}
doSomething(successCallback, failureCallback);
//这么写了:
let promise = doSomething(); 
promise.then(successCallback, failureCallback);
//更简洁的:
doSomething().then(successCallback, failureCallback);
//这种写法的要点: dosomething不需要后面的参数, then才需要.
//dosomething返回的函数是一个也已用then处理successCallback, failureCallback的函数.

  
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
//更简单写法: 
let promise2 = doSomething().then(successCallback, failureCallback);

//多重回调, 会导致括号套括号.
                                        doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

//基于promise的链式写法
doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

//then里的参数是可选的,catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。也可以用 arrow functions(箭头函数)来表示:
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
                                        
//举例
                                        
new Promise((resolve, reject) => {
    console.log('Initial');

    resolve();
})
.then(() => {
    throw new Error('Something failed');
  //由于“Something failed”错误导致了拒绝操作,所以“Do this”文本没有被输出   
    console.log('Do this');
})
.catch(() => {
    console.log('Do that');
})
.then(() => {
    console.log('Do this whatever happened before');
});

参考: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

promise和错误传递

doSomething()
.then(result => doSomethingElse(value))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log(`Got the final result: ${finalResult}`))
.catch(failureCallback);
//语法糖形式:
async function foo() {
  try {
    let result = await doSomething();
    let newResult = await doSomethingElse(result);
    let finalResult = await doThirdThing(newResult);
    console.log(`Got the final result: ${finalResult}`);
  } catch(error) {
    failureCallback(error);
  }
}

promise 和settimeout

//理想状态下,所有的异步函数都已经返回promise了。但有一些API仍然使用旧式的被传入的成功或者失败的回调。典型的例子就是setTimeout()函数, 所以要用promise包裹.
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);
//通常,promise的构造器会有一个可以让我们手动操作resolve和reject的执行函数。既然 setTimeout 没有真的执行失败,那么我们可以在这种情况下忽略reject。

new async/await/Promise 这三个是一套.

我理解的promise

xxx().then(成功函数, 失败函数).then(成功函数, 失败函数).then(成功函数, 失败函数)
要想形成链式, 成功函数和失败函数的返回值也要是函数.
doSomething()
.then(result => doSomethingElse(result)) //当省略{}时,箭头函数将隐式返回
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(() => {    console.log('Do that');});
//catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。

promise的变形: async/await语法糖

async function foo() {
  try {
    let result = await doSomething();
    let newResult = await doSomethingElse(result);
    let finalResult = await doThirdThing(newResult);
    console.log(`Got the final result: ${finalResult}`);
  } catch(error) {
    failureCallback(error);
  }
}

promise对timeout的处理

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);