//! Promise对象 // Promise 就是 “承诺” 的意思。代表未来某个时间要发生的事。它的出现是为了更好的处理异步任务。 //! 1. 同步与异步 var a = 10; console.log(a); var b = 20; console.log(b); //COMMENT 上面代码 都属于 同步代码 即我们所说的同步任务 //! 同步的特点是,代码 是 自顶向下 一行一行的执行,只有当前行有返回值或者运算完成后,才会执行下一行代码。 var c = 10; console.log(c); // 定时器中回调函数 就是 异步代码 即我们所说的异步任务 setTimeout(() => { console.log('timer'); }, 1000); console.log('end'); // 上面代码 输出的顺序为 : 10,'end', 'timer' //! 上面代码 中 包含异步任务,特点是 异步任务不会阻塞同步任务的执行,如果下面还有同步任务,继续执行。也就说 同步任务 此时的执行优先级高于 异步任务。 //! 小结:在JavaScript中,常见的异步任务: /** * 1. 事件处理函数 * 2. 定时器 setTimeout 和 setInterval * 3. 网络请求Ajax * 4. Promise对象 * */ //! 2. 创建Promise对象 // 语法 const promise = new Promise(executor) const promise = new Promise((resolve, reject) => { // executor 是同步的回调函数,当new Promise的时候executor会立即执行。 // 这里就是 要编写的异步任务 setTimeout(() => { // 1.5s后 该异步任务会执行 // 执行后,要给Promise对象设置状态(成功或者失败),以及异步任务的结果 // 在 executor中 会接收两个参数 resolve 和 reject // resolve(value) 将Promise对象的状态设置为成功的(fulfilled),并将参数value设置为成功的结果值 // reject(reason) 将Promise对象的状态设置为失败的(rejected),并将参数reason设置为失败的原因 let n = Math.random(); // 创建一个随件数 // 如果n大于 0.5 那么成功,结果值 为 n if (n > 0.5) { resolve(n); reject(); // 这里并不会 将promise状态修改为 失败的。由于上面已经调用resolve了 此reject会被忽略 } else { // 否则 失败,失败的原因 为 '你太小了' reject('你太小了'); } }, 1500); }); console.log(promise); //! 3. 获取Promise对象结果 // promise.then( // (value) => { // console.log('你成功了,值为:', value); // }, // (reason) => { // console.log('你拜拜了,因为:', reason); // } // ); //! promise对象的then方法会返回一个新的Promise对象 //! 4. Promise对象 还有一个 专门用于处理失败的方法 catch promise .then((value) => { console.log('你成功了,值为:', value); }) .catch((reason) => { console.log('你拜拜了,因为:', reason); }); //COMMENT 上面代码 由于then方法没有传入失败的处理函数,因此一旦promise失败了,就会将状态和结果都交给then返回的新Promise对象上,然后就可以通过新Promise对象调用catch方法去处理失败的情况了。 //! 5 静态方法 就是 构造函数的方法 Promise.resolve(value) // 直接返回一个Promise对象,通过状态为 成功的,以及成功的值为value参数。value可以为任何值。 console.log(Promise.resolve(1)); //! 6 静态方法 就是 构造函数的方法 Promise.reject(reason) // 直接返回一个Promise对象,通过状态为 失败的,以及失败的原因为reason参数。reason可以为任何值。 console.log(Promise.reject('我就失败了咋地!!!')); //! 6 回调地狱 // 举栗子: // 假如 有3个定时器:A - 1s后执行,B - 3s后执行,C - 2s后执行,但是要求 A 执行后 在执行B,B执行后 在执行C。 setTimeout(() => { console.log('任务A完事了'); // 开启任务B setTimeout(() => { console.log('任务B完事了'); setTimeout(() => { console.log('任务C完事了'); }, 2000); }, 3000); }, 1000); //! 在上述代码中的实现 你会发现 setTimeout中的回调函数 一直在嵌套下去,一旦这种异步任务 需要有序的、像同步任务那样一个一个的执行,就会产生一种现象--回调地狱。影响代码的可读性,也就说维护这样的代码会变得困难。 //! 6.1 使用Promsie对象来解决 function taskA() { return new Promise((resolve) => { setTimeout(() => { resolve('任务A完事了'); }, 1000); }); } function takB() { return new Promise((resolve) => { setTimeout(() => { resolve('任务B完事了'); }, 3000); }); } function taskC() { return new Promise((resolve) => { setTimeout(() => { resolve('任务C完事了'); }, 2000); }); } taskA() .then((v) => { console.log(v); return taskB(); }) .then((v) => { console.log(v); return taskC(); }) .then((v) => { console.log(v); }); //! 由于AP.then方法中的回调函数 指定了 返回值 为 一个新的Promise对象BP,因此 AP.then方法它自己返回的Promise对象的状态就和BP关联,同理后面也是一样的道理。 var p1 = Promise.resolve(1).then((v) => { console.log(`output->v`, v); }); console.log(p1); // p1 就是 then方法返回值Promise对象 var p2 = Promise.reject(1).catch((v) => { console.log(`output->v`, v); }); console.log(p2); // p2 就是 catch方法返回值Promise对象