本篇译自:blog.bitsrc.io/5-common-mi…
本瓜一直觉得 Promise 就是咱 JS 人的浪漫,没错,Promise 天天见,但或许越熟悉越陌生,我们在一直用的过程中会形成一些定式,这导致难免会漏掉一些定式以外的要点;
本篇带来 Promise 5 个避免,以供自查!!
1. 避免回调地狱
啥?Promise 就是来解决回调地狱的,如果还写成这个样子,那一切还有什么意义?
userLogin('user').then(function(user){ getArticle(user).then(function(articles){ showArticle(articles).then(function(){ //Your code goes here... }); }); });
正确写法如下:
userLogin('user') .then(getArticle) .then(showArticle) .then(function(){ //Your code goes here... });
当然,如果处理函数包含异步过程,记得是返回 Promise 对象:
new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 1000); }).then(function(result) { alert(result); // 1 return new Promise((resolve, reject) => { // (*) setTimeout(() => resolve(result * 2), 1000); }); }).then(function(result) { // (**) alert(result); // 2 return new Promise((resolve, reject) => { setTimeout(() => resolve(result * 2), 1000); }); }).then(function(result) { alert(result); // 4 });
2. 避免 Promise 中 try catch
在 Promise 中使用 try...catch...
,如果出现错误将不会走到 Promise.catch()
,所以,要避免在 Promise 中 try catch;
new Promise((resolve, reject) => { try { const data = doThis(); // do something resolve(); } catch (e) { reject(e); } }) .then(data => console.log(data)) .catch(error => console.log(error));
Promise 本身可以在没有 try/catch 块的情况下捕获其范围内的所有错误(甚至是错别字):
new Promise((resolve, reject) => { const data = doThis(); // do something resolve() }) .then(data => console.log(data)) .catch(error => console.log(error));
3. 避免错误使用 async await
Async/Await 是一种更高级的语法,用于处理同步代码中的多个 Promise。当我们在函数声明之前使用 async 关键字时,它会返回一个 Promise,我们可以使用 await 关键字来停止代码,直到正在等待的 Promise 得以解决或拒绝;
但是将 Async 函数放入 Promise 中,它会产生一些副作用!
比如以下代码将不会捕捉到错误:
// This code can't handle the error new Promise(async () => { throw new Error('message'); }).catch(e => console.log(e.message));
正确写法:
(async () => { try { await new Promise(async () => { throw new Error('message'); }); } catch (e) { console.log(e.message); } })();
在某些情况下,可能需要在 Promise 中实现 async
,此时,只能使用 try/catch 手动管理它:
new Promise(async (resolve, reject) => { try { throw new Error('message'); } catch (error) { reject(error); } }).catch(e => console.log(e.message)); //using async/await (async () => { try { await new Promise(async (resolve, reject) => { try { throw new Error('message'); } catch (error) { reject(error); } }); } catch (e) { console.log(e.message); } })();
4. 避免声明即运行
当我们写出以下代码,内部请求将会立即执行;
const myPromise = new Promise(resolve => { // code to make HTTP request resolve(result); });
但是我们的期望是,调起它的时候才执行,所以我们在外部封装一层函数;
const createMyPromise = () => new Promise(resolve => { // HTTP request resolve(result); });
这样做的好处就是,当用它的时候,它才执行,而不是我声明它的时候,就执行了~
将 Promise 惰性处理✔ 没错,又是函数式编程中惰性求值的思想!!
5. 避免遗漏使用 Promise.all()
没使用 Promise.all()
是这样的:
const { promisify } = require('util'); const sleep = promisify(setTimeout); async function f1() { await sleep(1000); } async function f2() { await sleep(2000); } async function f3() { await sleep(3000); } (async () => { console.time('sequential'); await f1(); await f2(); await f3(); console.timeEnd('sequential'); })();
使用 Promise.all()
是这样的:
(async () => { console.time('concurrent'); await Promise.all([f1(), f2(), f3()]); console.timeEnd('concurrent'); })();
高下立见!Promise 提供的衍生的一些 API 就是拿来用的(Promise.all、Promise.race、Promise.finally 等待),该用就用,别客气~
OK,以上就是本篇分享啦~
撰文不易,点赞鼓励👍👍👍👍👍👍