原生JS实现Promise
ES6中Promise可以说很大情况下改善了异步回调的嵌套问题,那么如果我们自己去写一个类似Promise的库应该怎么去写?
我们先看一下Promise的特点:
第一:Promise构造函数接受一个函数作为参数,函数里面有两个参数resolve和reject分别作为执行成功或者执行失败的函数
var promise=new Promsie(function(resolve,rejec){
if(/*异步执行成功*/){
resolve(value);
}else{
reject(error);
}
})
第二:可以通过then设置操作成功之后的操作,接受两个函数作为参数
.then(function(){
//回调执行成功之后的操作
},function(){
//回调执行失败之后的操作,可以没有
});
那么原生js实现以上特点应该比较简单了
function PromiseM(){
this.status='pending';
this.msg='';
var process=arguments[];
var that=this;
process(function(){
that.status='resolve';
that.msg=arguments[];
},function(){
that.status='reject';
that.msg=arguments[];
});
return this;
}
PromiseM.prototype.then=function(){
if(this.status=='resolve'){
arguments[](this.msg);
}
if(this.status=='reject'&&arguments[]){
arguments[](this.msg);
}
}
//测试用例
var mm=new PromiseM(function(resolve,reject){
resolve('123');//123其实就是第二个arguments[0]
});//上面的第一个arguments[0]
mm.then(function(success){
console.log(success);//该success其实就是上面的this.msg
console.log("ok!");
},function(){
console.log('fail!');
});
//123
//ok
以上只是最基本的实现,在代码结构结构和容错方面没有进行考虑。
对ES6里promise对象以及异步机制的理解
我现在声明一个a,并且要延时1秒钟后给他赋值为10,然后打印这个a:
var a;
setTimeout(function (){
a = ;
},);//1000ms后给a赋值为10
console.log(a)//undefined,
很显然,a是undefined,因为js是非阻塞的,它不会等你定时器里的东西走完了,再执行打印a这个操作。它不等你读完,就会迫不及待地去打印a,因为a要1秒后才能被赋值,所以此时a只是个undefined。
那怎么办?很简单,把打印a这个操作也放进延时定时器里嘛,我想这个例子并不难理解,那么接下来我会试图将其功能进行拓展,打印a这个需求我并不需要,我想要用a做其他事情,比如让他乘以2并输出返回结果,或者其他的涉及到a的操作。那很简单,我将console.log(a)这段代码删去,封装成一个函数,并将其作为参数传进这个定时器里,也就是所谓的“回调函数”如下:
var a;
function foo(callBack){
setTimeout(function (){
a = 10;
callBack&&callBack()
},)
} foo(function (){ //因为a是全局的,所以不需要将a传参进foo的回调中
return a*
})
调用foo的时候,作为参数的这个匿名函数,就是所谓的回调函数,回调函数这个机制极大地增加了代码的可能性,你可以在回调中做任何事,并且在不同的地方进行调用,你也将得到不同的反馈,如果将一个函数执行过程看成一个时间轴,那回调函数就可以允许你在这个过程中的各个时刻内执行其他代码,例如你可以将Vue.js的生命周期钩子函数看成是不同时期的回调函数
回调函数的作用显而易见,但如果一层回调套一层回调的话,代码极其不方便阅读与修改,因此ES6提供了Promise构造函数,从形式上改善了回调地狱。
var a;
var p = new Promise(function (resolve,reject){
setTimeout(function (){
a = ;
resolve();/*reject也就是失败时对应的函数,由于这个例子比较简单,就不再赘述,毕竟是面向新手的*/
},)
}).then(function (){
console.log(a)
})
现在我们就以一个人起床后的行为为例来深入理解异步执行机制,来看代码:
getup();
wearClothes();
brushTeeth();
washFace();
eatBreakfast();
goToCompany();
因为js是异步执行的,所以如果这么写,逻辑上等同于一个人同时开始做“起床+穿衣+刷牙+洗脸+吃早饭+出门上班”这些事,显然是不可能的事情,与我们想要的结果大相径庭,依照回调函数的写法,我们会在上述每个行为结束之后(即函数执行完毕的我们想要让他做什么,例如$.ajax()的success)传入一个回调函数,并将下一步的函数写进回调里,环环相扣,写法比较恶心,相当难以维护。
var p = new Promise(function (resolve){
getUp(function (){
resolve();
});
}).then(function (){
return new Promise(function (resolve){
wearClothes(function (){
resolve();
});
})
}).then(function (){
return new Promise(function (resolve){
brushTeeth(function (){
resolve();
});
})
}).then(function (){
return new Promise(function (resolve){
washFace(function (){
resolve();
});
})
}).then(function (){
return new Promise(function (resolve){
eatBreakfast(function (){
resolve();
});
})
}).then(function (){
goToCompany()
})
如果要链式调用then的话,必须要注意的一点是,一定要在then里的回调函数return一个新的promise对象,否则执行顺序将向上开始查找,直到找到最近的promise实例。
写到这里大家会发现promise并没有改变什么,只是把异步代码的书写形式从水平方向改为了竖直方向,让代码更符合人类的阅读习惯
原生JS实现Promise的更多相关文章
- 原生js实现canvas气泡冒泡效果
说明: 本文章主要分为ES5和ES6两个版本 ES5版本是早期版本,后面用ES6重写优化的,建议使用ES6版本. 1, 原生js实现canvas气泡冒泡效果的插件,api丰富,使用简单2, 只需引入J ...
- 【面试篇】寒冬求职季之你必须要懂的原生JS(中)
互联网寒冬之际,各大公司都缩减了HC,甚至是采取了“裁员”措施,在这样的大环境之下,想要获得一份更好的工作,必然需要付出更多的努力. 一年前,也许你搞清楚闭包,this,原型链,就能获得认可.但是现在 ...
- 原生js替换jQuery各种方法-中文版
原文https://github.com/nefe/You-D... 原生JS与jQuery操作DOM对比 You Don't Need jQuery 前端发展很快,现代浏览器原生 API 已经足够好 ...
- 用原生js写一个"多动症"的简历
用原生js写一个"多动症"的简历 预览地址源码地址 最近在知乎上看到@方应杭用vue写了一个会动的简历,觉得挺好玩的,研究一下其实现思路,决定试试用原生js来实现. 会动的简历实现 ...
- 基于原生JS实现的Bean容器和AOP编程
Bean是什么 我们知道Bean是Spring最基础的核心构件,大多数逻辑代码都通过Bean进行管理.NestJS基于TypeScript和依赖注入也实现了类似于Spring Bean的机制:服务提供 ...
- 原生JS封装Ajax插件(同域&&jsonp跨域)
抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...
- 常用原生JS方法总结(兼容性写法)
经常会用到原生JS来写前端...但是原生JS的一些方法在适应各个浏览器的时候写法有的也不怎么一样的... 今天下班有点累... 就来总结一下简单的东西吧…… 备注:一下的方法都是包裹在一个EventU ...
- 原生JS实现"旋转木马"效果的图片轮播插件
一.写在最前面 最近都忙一些杂七杂八的事情,复习软考.研读经典...好像都好久没写过博客了... 我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的, ...
- 再谈React.js实现原生js拖拽效果
前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...
随机推荐
- codevs 5929 亲戚
5929 亲戚 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不 ...
- BZOJ4175 : 小G的电话本
用后缀树统计出出现了x次的本质不同的子串的个数,最后再乘以x,得到一个多项式. 这个多项式常数项为0,但是一次项不为0. 于是把整个多项式除以一次项,通过多项式求ln和多项式求exp求出它的幂. 最后 ...
- django orm 优化
.markdown-body hr::after,.markdown-body::after{clear:both}.loopLine,.messageLine0{marker-end:"u ...
- Codeforces Round #281 (Div. 2) B. Vasya and Wrestling 水题
B. Vasya and Wrestling 题目连接: http://codeforces.com/contest/493/problem/B Description Vasya has becom ...
- MikroTik RouterOS安装方法收集(转)
注意:ROS无法使用U盘安装,如果要使用ISO文件进行安装就必须使用光驱以及刻录成光盘,并且只能使用IDE的光驱. 一.首先了解常见的ROS硬件架构: X86架构(也是最常用的) mipsbe(欧米t ...
- LPC43xx Asymmetric Dual Core : Cortex-M0 and Cortex-M4
- OpenOCD 0.9.0 release
OpenOCD 0.9.0 release May 18th, 2015 I’m happy to announce the release of OpenOCD version 0.9.0, fin ...
- ubuntu修改时区和时间的方法
改时区参考 http://blog.sina.com.cn/s/blog_6c9d65a1010145st.html 1.首先查看时区: swfsadmin@swfsubuntu:~$ date -R ...
- 天蝎第一季/全集Scorpion迅雷下载
英文译名 Scorpion (第1季) (2014-秋季播出)CBS.本季看点:<天蝎>双名蝎子故事描述一个高深莫测的计算机专家和一群同样具备天才头脑的国际计算机黑客共同组建全球防御网络, ...
- Lua调用C++时打印堆栈信息
公司的手游项目,使用的是基于cocos2d-x绑lua的解决方案(参数quick-x的绑定),虽然使用了lua进行开发,更新很爽了,但是崩溃依然较为严重,从后台查看崩溃日志时,基本上只能靠" ...