setTimeout(function(){}) 堆栈 ES6 Promise

/*
*SetTimeout()的用法
*回调函数
*/

var learingSetOneTime = null;
var learingSetSecondTime = null;

function learningSetTimeout(){
    console.log(a);
    learingSetOneTime = setTimeout(function(){
        console.log(a);
    },0);
    learingSetSecondTime = setTimeout(function(){
        console.log(a);
    },1000);
    var a = 2;
}

输出结果:undefined 2 2

还是那句话 同步 异步 回调

/*
*在这讨论下之前在知乎看到的 80% 应聘者都不及格的 JS 面试题setTimeout
*因为涉及到我还比较感兴趣的ES6,所以我也来谈一谈
*/

function showSetResult(){
    for(var i = 0; i < 5; i++){
        setTimeout(function(){
            console.log(i);
        },1000);
    }
}
showSetResult();
//输出结果:在这里提个建议:凡是看到代码,在情况允许的条件下还是在电脑上跑一下比较好,自己看下结果 == > 隔1秒一次性输出5个5;

至于原因还是那句话:回调函数
/*
*回调函数的执行:这里涉及到javascript单线程如何处理回调的?
*
*javascript的同步代码在JavaScript同步的代码是在堆栈中顺序执行的,而setTimeout回调会先放到消息队列,for循环每执行一次,就会放一个setTimeout到消息队列排队等候,当同步的代码执行完了,再去调用消息队列的回调方法。i是showSetResult()函数的局部变量没有记忆的过程,所以当同步函数执行完了之后for循环已经完成了,此时i的值为5.
*/

这里提到了堆栈的问题:
就简单提一下堆栈的问题:
什么是栈?存储原始数据类型和引用数据类型的实体的起始地址
原始数据类型:undefined、null、string、number、boolean,存储在栈(stack)中的简单段,占用空间小,大小固定,属于被频繁属于数据
什么是堆:存储引用类型实体
引用类型:Array、Object、function,占用空间大,大小不固定。通过起始地址的指针访问实体数据位置
当解析时,会先检索其再栈中的地址,取得地址之后再从堆中获取实体数据

/*
*进一步改进,输出0,1,2,3,4
*在javascript中没有块级作用域的问题(ES6有),通过立即执行函数可以实现块级作用域
*/

function showSetResult(){
    for(var i = 0; i < 5; i++){
        (function(i){
            setTimeout(function(){
                console.log(i);
            },1000);
        }(i))
    }
}
showSetResult();

/*
*立即执行函数:最外层的大括号是将括号里的函数作为函数表达式来解析,将i作为参数传给立即执行函数。相当于将i做了记忆,此时是隔一秒一次性输出0,1,2,3,4,我如果想要每隔一秒输出一个呢?
*/

function showSetResult(){
    for(var i = 0; i < 5; i++){
        (function(i){
            setTimeout(function(){
                console.log(i);
            },1000 * i);
        }(i))
    }
}
showSetResult();

/*
*此时输出就是每个一秒输出1个 数,0,1,2,3,4
*/

那ES6是怎么解决的呢?

上边提到了块级作用域:ES6的let定义的就是用来解决这个问题的

let:声明的变量只在块级作用域中有效
const:声明一个常量,一旦声明,常量的值就不能改变,只有在声明所在的块级作用域中有效
使用let声明的变量就不存在变量提升的问题了,在该变量声明之前,该变量是不可用的。

function showSetResult(){
    for(let i = 0; i < 5; i++){
        setTimeout(function(){
            console.log(i);
        },1000 * i);
    }
}
showSetResult();

/*
*此时你可以运行看看,结果是Error
*/
这就是let,let的作用域是当前块。也就是for循环。在for中声明的let在setTimeout中是不可用的。在这里let本身就形成了一个闭包。外部是不能访问的。

其实这个就相当于:

function showSetResult(){
    for(var i = 0; i < 5; i++){
        showI(i);
    }
}

function showI(i){
    setTimeout(function(){
        console.log(i);
    },1000 * i);
}

showSetResult();

所以说:let其实就是个语法糖,那使用ES6怎么完成呢?

怎么改呢?

const tasks = [];
(function(j){
    tasks.push(new Promise(function(resolve,reject){
       setTimeout(function(){
          console.log(j);
          resolve();  //调用resove,不调用的话就不会异步调用到then
       }, 1000 * j);  
  }));
}(i))
Promise.all(tasks).then(function(){
    setTimeout(function(){
        console.log(i);
    }, 1000);   // 注意这里只需要把超时设置为 1 秒
});

/*
*promise.all();
*参数数组的顺序一致,而不是按时间顺序排序
*如果数组中所有的Promise对象都resolve了,那么这些resolve的值将作为一个数组作为Promise.all这个方法的返回值的(Promise对象)的resolve值,之后可以被then方法处理。如果数组中任意的Promise被reject,那么该reject的值就是Promise.all方法的返回值的reject值.
*Promise.race()
*不是等待所有的promise被resolve或reject,而是所有的promise中只要有一个执行结束,它就会触发
*/

promises的真正强大之处在于多重的链接 == >
特性:
1)只有来自上一层的异常可以被捕捉
2)错误可以被恢复 == > 在一个错误回调函数中,如果你不重新抛出错误,promise会假设你已经从错误中恢复,并且反转成为已解决状态
3)Promises可以被暂停
4)Resolved Promises并不会立刻执行

两种情形:
1)假设传入的参数没有一个.then方法,那么这个返回的Promise对象变成了resolve状态,其resolve的值就是这个对象本身。
2)假设传入的参数带有一个then方法(称为thenable对象), 那么将这个对象的类型变为Promise,其then方法变成Promise.prototype.then方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值