本瓜一直觉得 Promise 就是咱 JS 人的浪漫,没错,Promise 天天见,但或许越熟悉越陌生,我们在一直用的过程中会形成一些定式,这导致难免会漏掉一些定式以外的要点;

本篇带来 Promise 5 个避免,以供自查!!

JS 的浪漫 ——  Promise 食用注意点_封装

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 等待),该用就用,别客气~