发音:[ˈprɒmɪs] 词性:名词, 翻译:许诺,允诺。
能够将异步操做的书写方式变成一种队列化的书写方式,并按照咱们写的那样的预期来执行返回符合预期的结果。javascript
js为检查表单而生,其首要目标是操做dom,界面冻结会形成很是不友好的用户体验,因此dom操做大可能是异步的。
注意:同步操做的处理器未执行完成会使得界面没法响应用户的其余操做,而异步操做则能够避免该问题。
常见的异步操做语法:java
$('#start').on('click',startHandler); function startHandler(){} // 定义事件响应的处理器函数
用户点击start元素就会触发一个异步事件去执行,再次触发没必要等待前一次事件执行完成,就能够再次触发。node
$.ajax('http://baidu.com',{ success:function(res){ // 成功回调处理器 }, error:function(e){ // 失败回调处理器 } });
用户发送一个向百度服务器获取数据的异步请求ajax
更加严重的依赖异步操做才能完成无阻赛高并发的特性。数组
然而异步回调这种方式并非理想的,它却有一些问题,
好比:promise
更深层次的问题:服务器
一个promise的基本使用案例:并发
new Promise( // 执行器 executor function ( resolve, reject ) { //一段耗时很长的异步操做 resolve(); //异步处理成功 reject(); // 异步处理失败 //注意:resolve和reject这俩个回调函数被调用是互斥的 } ).then( function A(){ //成功,下一步 }, function B(){ //失败,作善后处理 } );
pending 初始状态 fulfilled 操做成功 rejectd 操做失败dom
//范例1 console.log('here we go'); new Promise( resolve => { setTimeout( () => { resolve('hello'); }, 2000); }).then( value => { console.log( value + ' world'); }); /* 控制台日志 */ here we go // 2s之后 hello world
// 范例2 console.log('here we go'); new Promise(resolve => { setTimeout( () => { resolve('hello'); }, 2000); }).then(value => { console.log(value); return new Promise( resolve => { setTimeout(() => { resolve('world'); }, 2000); }); }).then(value => { console.log( value + ' world'); }); /* 控制台日志 */ here we go // 2s后 hello // 2s后 world world
// 假如一个Promise已经完成了,再.then()会怎样?异步
console.log('start'); let promise = new Promise(resolve => { setTimeout(() => { console.log('the promise fulfilled'); resolve('hello, world'); }, 1000); }); setTimeout(() => { promise.then( value => { console.log(value); }); }, 3000); /* 控制台 */ 17:37:29.015 start 17:37:30.016 the promise fulfilled 17:37:32.017 hello, world
// 假如在.then()的函数里面不返回新的Promise,会怎样?
console.log('here we go'); new Promise(resolve => { setTimeout( () => { resolve('hello'); }, 2000); }).then( value => { console.log(value); console.log('everyone'); (function () { return new Promise(resolve => { setTimeout(() => { console.log('Mr.Laurence'); resolve('Merry Xmas'); }, 2000); }); }()); // return false; }).then( value => { console.log(value + ' world'); return 0 }).then( value => { console.log(value + ' world'); }).then( value => { console.log(value + ' world'); }); /* 控制台 */ 17:53:03.175 here we go 17:53:03.191 Promise {<pending>} 17:53:05.181 hello 17:53:05.181 everyone 17:53:05.181 undefined world 17:53:05.182 0 world 17:53:05.182 undefined world 17:53:07.187 Mr.Laurence 从日志能够看出, 1. 执行器中必须回调resolve或者reject改变promise的状态; 2. 当状态改变后继续调用then方法,可是promise中的状态已经没法改变了; 3. 能够看到promise对象帮咱们生成了一个队列,这个队列一直存在。
测试
问题:下面四种Promise的区别是什么?
前提:doSomething方法和doSomethingElse方法均返回一个promise实例。 // #1 doSomething().then(function() { return doSomethingElse(); }); // #2 doSomething().then(function(){ doSomethingElse(); }); // #3 doSomething().then(doSomethingElse()); // #4 doSomething().then(doSomethingElse);
// 解析: // #1 doSomething().then(function() { return doSomethingElse(); }); //符合预期的,能够继续回调then方法获取doSomethingElse的结果 // #2 doSomething().then(function(){ doSomethingElse(); }); //then中没有返回promise,因此以后的then没法获取到doSomethingElse的结果,而且与doSomethingElse几乎同时执行 // #3 doSomething().then(doSomethingElse()); // then应该接收一个状态处理函数,当前这种状况传入了一个promise实例,没法获取上层promise的结果,而该层then会被忽略,下一层会获取到doSomething()的结果 // #4 doSomething().then(doSomethingElse); // then方法中吧doSomethingElse直接当成状态处理函数也是能够达到预期的
catch和then同样会返回一个promise实例。若是没有抛出错误,该实例默认也会返回fulfilled状态。
promise.all
接收一个数组参数,返回一个新的promise实例,响应函数中的结果为数组中的每一个promise的结果。
与map连用
使用forEach和reduce实现队列
ES2017 的async/await
该学习笔记是学习慕课网中 Promise入门 记录