Promise问答
本文主要针对这篇文章提出的问题,做个解答。
1.了解 Promise 吗?
Promise是一种异步编程的解决方案,有三种状态,pending(进行中)、resolved(已完成)、rejected(已失败)。当Promise的状态由pending转变为resolved或reject时,会执行相应的方法。
特点:
1、只有异步操作的结果,可以决定当前是哪一种状态,任务其他操作都无法改变这个状态,也是“Promise”的名称的由来。
2、状态一旦改变,就无法再次改变状态。
2.Promise 解决的痛点是什么?
1、回调地狱带来的负面作用:代码臃肿,可读性差,只能在回调里处理异常。。
2、事件,事件的特点是如果你错过了它,再去监听,是得不到结果的。而Promise如果改变已经发生了,你再对Promise
对象添加回调函数,也会立即得到这个结果。
3.Promise 解决的痛点还有其他方法可以解决吗?如果有,请列举。
setTimeout、事件监听、回调函数、Generator函数,async/await
1、setTimeout:缺点不精确,只是确保在一定时间后加入到任务队列,并不保证立马执行。只有执行引擎栈中的代码执行完毕,主线程才会去读取任务队列。
2、事件监听:任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
3、Generator函数虽然将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。即如何实现自动化的流程管理。
4、async/await
4.Promise如何使用
1、创建实例
//创造一个Promise实例。 const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } }); //Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。 promise.then(function(value) { // success }, function(error) { // failure });
2、可用Promise的try和catch方法预防异常
Promise.try(database.users.get({id: userId})) .then(...) .catch(...)
5.Promise 常用的方法,方法的作用?
1、Promise.prototype.then()、Promise.prototype.catch()、Promise.prototype.finally()、Promise.all()、Promise.race()、Promise.resolve()、Promise.reject()。
2、Promise.all
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.all([p1, p2, p3]);
//只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled。
3、Promise.race
方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.race([p1, p2, p3]);
//只有p1、p2、p3有一个实例率先改变状态,p的状态就跟着改变。
//下面是一个例子,如何指定时间内没有获取结果,就将promise的状态变为reject,否则变为resolve。
const p = Promise.race([ fetch('/resource-that-may-take-a-while'), new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('request timeout')), 5000) }) ]); p .then(console.log) .catch(console.error);
6.Promise 在事件循环中的执行过程是怎样的?
首先什么是事件循环?看下这篇文章,https://www.cnblogs.com/xiaohuochai/p/8527618.html。简要提取下就是:
从代码执行顺序的角度来看,程序最开始是按代码顺序执行代码的,遇到同步任务,立刻执行;遇到异步任务,则只是调用异步函数发起异步请求。此时,异步任务开始执行异步操作,执行完成后到消息队列中排队。程序按照代码顺序执行完毕后,查询消息队列中是否有等待的消息。如果有,则按照次序从消息队列中把消息放到执行栈中执行。执行完毕后,再从消息队列中获取消息,再执行,不断重复。
由于主线程不断的重复获得消息、执行消息、再取消息、再执行。所以,这种机制被称为事件循环
promise的构造部分是同步执行,script(主程序代码)—>process.nextTick—>Promises...——>setTimeout——>setInterval——>setImmediate——> I/O——>UI rendering。引用文章:https://github.com/forthealllight/blog/issues/5
setTimeout(function(){console.log(1)},0); new Promise(function(resolve,reject){ console.log(2); resolve(); }).then(function(){console.log(3) }).then(function(){console.log(4)}); process.nextTick(function(){console.log(5)}); console.log(6); //输出2,6,5,3,4,1
7.能不能手写一个 Promise 的 polyfill。
https://github.com/stefanpenner/es6-promise