1、Promise 的含义
初识Promise,要从多方面去理解,可以直接百度Promise,只看别人博客的前面的含义介绍,先不深入看别人的博客,基本可以了解到:
- promise原意:诺言; 许诺; 承诺;预示。
- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。链接描述
- Promises 是一种 JavaScript 中处理异步代码的方法,其实 Promises 已经存在多年,但是直到 ES2015 (ES6)才被标准化和引入,现在它们已经在 ES2017(ES8) 中被 async(异步) 函数所取代和扩展,可见发展之快。链接描述
- 一个 Promise 就是一个对象,它代表了一个异步操作的最终完成或者失败。链接描述
- Promise对象用于异步操作,它表示一个尚未完成且预计在未来完成的异步操作。
- ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。
- Async functions(异步函数) 使用 promises API 作为构建块,因此理解 Promises 是必须的,即使在较新的代码中,你可能会使用 async(异步) 函数而不是promises 。链接描述
2、同步、异步、回调函数相关概念
- 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.
也就是说,回调函数不仅可以用于异步调用,一般同步的场景也可以用回调。
在同步调用下,回调函数一般是最后执行的。而异步调用下,可能一段时间后执行或不执行(未达到执行的条件)。
3、Promise 的特点和基本用法
promise对象有两个特点:
- 对象的状态不受外界影响,pending(进行中)、fulfiled(已完成)、rejected(已失败)
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果,状态改变只有两种可能,称为(resolved)
基本用法:
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)去掉,结果如下:
4、解读promise中唯一的参数、resolve参数、reject参数、then()、catch()方法的意义
参考上面例子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也是相同的道理。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。