JS-原生/对于promise对象以及异步机制的理解
来源:互联网 发布:自学绘画知乎 编辑:程序博客网 时间:2024/05/16 01:54
promise是ES6新增的语法,他的出现极大地改善了异步编程中“回调地狱”的情况,promise究竟有什么用呢?在踩了很多坑之后,我总结出了一套自己对于promise的理解,本文争取用一段最简单的代码,让新手秒懂promise的用法,老鸟轻拍!
我现在声明一个a,并且要延时1秒钟后给他赋值为10,然后打印这个a:
var a;setTimeout(function (){a = 10;},1000);//1000ms后给a赋值为10console.log(a)//undefined,
很显然,a是undefined,因为js是非阻塞的,它不会等你定时器里的东西走完了,再执行打印a这个操作。
它不等你读完,就会迫不及待地去打印a,因为a要1秒后才能被赋值,所以此时a就像一个早产儿一样,只是个undefined。
那怎么办?很简单,把【打印a】这个操作也放进延时定时器里嘛:
setTimeout(function (){a = 10;console.log(a);//成功打印为10},1000);
我想上一个例子并不难理解,那么接下来我会试图将其功能进行拓展,【打印a】这个需求我并不需要,我想要用a做其他事情,比如让他乘以2并输出返回结果,或者其他的涉及到a的操作。那很简单,我将console.log(a)这段代码删去,封装成一个函数,并将其作为参数传进这个定时器里,也就是所谓的“回调函数”如下:
var a;function foo(callBack){setTimeout(function (){a = 10;callBack&&callBack()},1000)}foo(function (){ //因为a是全局的,所以不需要将a传参进foo的回调中return a*2})
调用foo的时候,作为参数的这个匿名函数,就是所谓的回调函数,回调函数这个机制极大地增加了代码的可能性,你可以在回调中做任何事,并且在不同的地方进行调用,你也将得到不同的反馈,如果将一个函数执行过程看成一个时间轴,那回调函数就可以允许你在这个过程中的各个时刻内执行其他代码,例如你可以将Vue.js的生命周期钩子函数看成是不同时期的回调函数
回调函数的作用显而易见,但如果一层回调套一层回调的话,代码极其不方便阅读与修改,因此ES6提供了Promise构造函数,从形式上改善了回调地狱。
上述打印a的例子可以改为:
var a;var p = new Promise(function (resolve,reject){setTimeout(function (){a = 10;resolve();/*reject也就是失败时对应的函数,由于这个例子比较简单,就不再赘述,毕竟是面向新手的*/},1000)}).then(function (){console.log(a)})
看似很复杂,实际上只要记住一点,resolve对应的是then的第一个回调函数,reject对应的是then的第二个回调函数,原本回调版的代码顺序咋写的,promise还是咋写,只不过把异步执行(即需要等待数据的部分,比如我那个打印a,或者取一张img的width)的部分写进then的回调里,然后把resolve当作这个位于then里的回调,在老地方进行调用就行了(reject同理)
现在我们就以一个人起床后的行为为例来深入理解异步执行机制,来看代码:
getup();wearClothes();brushTeeth();washFace();eatBreakfast();goToCompany();
因为js是异步执行的,所以如果这么写,逻辑上等同于一个人同时开始做“起床+穿衣+刷牙+洗脸+吃早饭+出门上班”这些事,显然是不可能的事情,与我们想要的结果大相径庭,依照回调函数的写法,我们会在上述每个行为结束之后(即函数执行完毕的我们想要让他做什么,例如$.ajax()的success)传入一个回调函数,并将下一步的函数写进回调里,环环相扣,就像这样:
getUp(function (){wearClothes(function (){brushTeeth(function (){washFace(function (){eatBreakfast(function (){goToCompany()})})})})})
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并没有改变什么,只是把异步代码的书写形式从水平方向改为了竖直方向,让代码更符合人类的阅读习惯
关于promise的初步入门就先到这,若有错误欢迎指出。
- JS-原生/对于promise对象以及异步机制的理解
- 深入理解JS异步编程三(promise)
- JS异步编程(promise、deferred对象)
- 原生JS实现Promise
- promise 异步加载的 自我理解
- 对于RAC心跳以及仲裁机制的理解
- Promise处理JS异步的问题
- json字符串和对象转换以及json2.js和jquery.json-2.3.js中对于json的方法定义理解
- JS异步操作-promise
- 理解Promise机制
- JavaScript中对Promise对象的理解
- js中promise的使用与理解
- 对于RTTI机制的理解
- 对于RTTI机制的理解
- Node.js用ES6原生Promise对异步函数进行封装
- 我对node js异步IO机制的理解
- ES6 Promise 对象理解
- 对js Promise理解
- 我们只知大势将至,却不知未来已来
- 手把手教你用 1 行命令实现人脸识别
- 错过等半年 | 年薪30万都要学的Linux云计算课程,即将满80人班
- //输入不同对象的姓名、性别、年龄、体重和住址等信息,并输出显示。
- 开源爱好者必看!开源许可证基础知识扫盲
- JS-原生/对于promise对象以及异步机制的理解
- 【PHP基础知识】——操作Email
- Android优秀库收集
- angular template的图片路径问题
- Python爬虫利器之selenium的安装
- 【C++】虚函数在不同继承方式中的对象模型
- sublime text3 插件
- 探究外部类访问内部类的可行性
- VIJOS 1083 小白逛公园 线段树