初识Promise,要从多方面去理解,能够直接百度Promise,只看别人博客的前面的含义介绍,先不深刻看别人的博客,基本能够了解到:
- promise原意:诺言; 许诺; 承诺;预示。
- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。连接描述
- Promises 是一种 JavaScript 中处理异步代码的方法,其实 Promises 已经存在多年,可是直到 ES2015 (ES6)才被标准化和引入,如今它们已经在 ES2017(ES8) 中被 async(异步) 函数所取代和扩展,可见发展之快。连接描述
- 一个 Promise 就是一个对象,它表明了一个异步操做的最终完成或者失败。连接描述
- Promise对象用于异步操做,它表示一个还没有完成且预计在将来完成的异步操做。
- ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
- Async functions(异步函数) 使用 promises API 做为构建块,所以理解 Promises 是必须的,即便在较新的代码中,你可能会使用 async(异步) 函数而不是promises 。连接描述
- JavaScript的执行环境是单线程。所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,它会阻塞其余任务。这个任务可称为主线程。但实际上还有其余线程,如事件触发线程、ajax请求线程等。
- 同步模式,即上述所说的单线程模式,一次只能执行一个任务,函数调用后需等到函数执行结束,返回执行的结果,才能进行下一个任务。若是这个任务执行的时间较长,就会致使线程阻塞。
/* 例2.1 */ var x = true; while(x); console.log("don't carry out"); //不会执行 上面的例子即同步模式,其中的while是一个死循环,它会阻塞进程,所以第三句console不会执行。 同步模式比较简单,也较容易编写。但问题也显而易见,若是请求的时间较长,而阻塞了后面代码的执行, 体验是很很差的。所以对于一些耗时的操做,异步模式则是更好的选择。
- 异步模式,即与同步模式相反,能够一块儿执行多个任务,函数调用后不会当即返回执行的结果,若是任务A须要等待,可先执行任务B,等到任务A结果返回后再继续回调。最多见的异步模式就数定时器了,咱们来看看如下的例子。
/* 例2.2 */ setTimeout(function() { console.log('taskA, asynchronous'); }, 0); console.log('taskB, synchronize'); //while(true); -------ouput------- taskB, synchronize taskA, asynchronous 咱们能够看到,定时器延时的时间明明为0,但taskA仍是晚于taskB执行。 这是为何呢?因为定时器是异步的,异步任务会在当前脚本的全部同步 任务执行完才会执行。 若是同步代码中含有死循环,即将上例的注释去掉,那么这个异步任务就不会执行,由于同步任务阻塞了进程。
- 回调函数,提起异步,就不得不谈谈回调函数了。上例中,setTimeout里的function即是回调函数。能够简单理解为:(执行完)回(来)调(用)的函数。
**WikiPedia对于callback的定义。** In computer programming, a callback is a piece of executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at some convenient time. 能够看出,回调函数是一段可执行的代码段,它以「参数」的形式传递给其余代码, 在其合适的时间执行这段(回调函数)的代码。 **WikiPedia还定义** The invocation may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback. 也就是说,回调函数不只能够用于异步调用,通常同步的场景也能够用回调。 在同步调用下,回调函数通常是最后执行的。而异步调用下,可能一段时间后执行或不执行(未达到执行的条件)。
promise对象有两个特色:
基本用法:
es6规定,Promise对象是一个构造函数,用来生成Promise实例。 扩展构造函数回顾:特殊方法,建立对象时初始化对象,为对象成员变量赋初始值,与new一块儿使用。 一个类能够有多个构造函数 ,可根据其参数个数的不一样或参数类型的不一样来区分它们 即构造函数的重载。 var promise = new promise(function(resove, reject){ // ... some code if (/*异步成功*/){ resove(value); } else{ reject(error);。 } });
简单例子1
例子用到了箭头函数,写法很容易理解,可参考另外一篇文章
let p= new Promise((resolve, reject)=>{ let a1='成功传出去的对象'; let a2='失败传出去的对象'; var timer = setTimeout(function () { console.log('after resolve'); resolve(a1); reject(a2); console.log('after error'); }, 1000); }); p.then(value=>{ console.log(value); },error=>{ console.log('.then的第二个参数'); console.log(error) }); p.catch(error=>{ console.log('.catch'); console.log(error); });
上面例子的输出效果,出现的第一行是Promise{<pending>},
而后再次输入p 按回车执行打印出来p是这样Promise{<resolved>}
而后点开看 能够看到控制台提示promiseStatus :resolved 说明promise的状态已经成为了resolved
上面例子把resolve(a1)去掉,结果以下:html
参考上面例子1
- let p = new Promise(参数1),创造一个实例时,接受一个函数做为参数1;
- 参数1,做为函数,也接受两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用本身部署。注意:这两个函数的做用就是改变Promise对象的状态,一个是成功,一个是失败,一旦调用了其中一个,状态就不可改变和逆转;
- Promise实例生成之后,能够用then方法分别指定resolved状态和rejected状态的回调函数,即便用p.then()来进一步的操做,注意:then()能够接受两个参数,这两个参数也是函数,第一个表示成功的操做,就是调用了resolve(a1)后会进入,第二个表示失败的操做,就是调用了reject(a1)后会进入,但第二个能够省略;
- p.catch和.then()第二个参数的效果是同样,都会进入;
- 例子1的resolve(a1)和reject(a2)同时存在时,只有在前面的有用,可注释第一个看失败的效果;
- 例子中的resolve,reject只是个名字,其实能够随便改,不建议改;
- 例子中p.then(value=>{console.log(value)},这里面的value也只是个名字,其实能够随便改,不建议改;注意:value就是上面resolve(a1)中传出来的a1,a1能够是任何对象,a2也是相同的道理。