最近在做 electron 开发,采用的是 electron + vue 两个独立工程的架构。在安装依赖时,涉及到 electron工程的依赖, vue工程的依赖还有在 win32 架构中指定安装 32 位的 electron。 在写安装依赖脚本时,使用了 Promise,所以这里对 Promise 的用法做一个总结。
Promise 概念
Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。这里更详细的可以参考 MDN 官方文档。
Promise必然处于以下几种状态之一:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled): 意味着操作成功完成。 => resolve()
- 已拒绝(rejected): 意味着操作失败。 => reject()
Promise 链式调用
我们可以用 promise.then(),promise.catch() 和 promise.finally() 这些方法将进一步的操作与一个变为已敲定状态的 promise 关联起来。这些方法还会返回一个新生成的 promise 对象,这个对象可以被非强制性的用来做链式调用。
NOTE: 当 .then() 中缺少能够返回 promise 对象的函数时,链式调用就直接继续进行下一环操作。
Promise 常用方法
-
。。。
-
Promise.all([array]) 返回 Promise,当 array 里所有的 Promise 都 resolve 才会触发。
-
Promise.any([array]) 返回 Promise, 当 array 里其中一个 Promise 结果为 resolve 就会触发。
Promise 使用例子
有 funcA, funcB, funcC 三个基本方法,要求:
- 顺序执行 funcA, funcB, funcC。
- 同步执行 funcA, funcB, 再执行 funcC。
- 步骤 1 执行完,再执行 步骤 2。
- 调用过程所有 error 统一处理。
下面分别用 3 种方法实现。
-
方法一: then 链式调用, 但是代码比较繁琐。
-
方法二: 构建了调用 queue,代码精简。
-
方法三: 使用 await async 方式构建调用 queue。
NOTE: 这里需要注意的是,在方法二和方法三中,传入的参数需要是 FUNCTION, 而不是 FUNCTION 执行后的结果。 因为要确保方法的执行顺序,所以需要 FUNCTION 在 promise 里执行。
具体代码如下,也可以参考 Gist。
// promise.js
// Method 1
// callInThenChain();
// Method 2
callInQueue();
// Method 3
// callInAsyncAwait();
function funcA() {
return new Promise((resolve, reject) => {
try {
console.log('Exec funcA');
resolve('a');
} catch (error) {
reject(error);
}
});
}
function funcB() {
return new Promise((resolve, reject) => {
try {
console.log('Exec funcB');
resolve('b');
} catch (error) {
reject(error);
}
});
}
function funcC() {
return new Promise((resolve, reject) => {
try {
console.log('Exec funcC');
resolve('c');
} catch (error) {
reject(error);
}
});
}
function funcD() {
return new Promise((resolve, reject) => {
try {
console.log('Exec funcD, test promise in promise');
// call funcA and funcB async
Promise.all([funcA(), funcB()])
.then(function () {
// call funcC sync
return funcC();
})
.then(function () {
// must call resolve to return thenable
resolve('d');
})
.catch((error) => reject(error));
} catch (error) {
reject(error);
}
});
}
function callInThenChain() {
console.log('> Call in then chain, the code is cumbersome. \n\n');
Promise.resolve()
.then(function () {
return funcA();
})
.then(() => {
console.log('The chain will go on if not return promise');
})
.then(function () {
return funcB();
})
.then(() => funcC())
.then(() => funcD())
.then((result) => console.log(`Finish ${result}`))
.catch(error => {
console.log(`Error: ${error}`);
})
}
function callInQueue() {
console.log('> Call in queue\n\n');
function queue(arr) {
var queue = Promise.resolve()
arr.forEach(function (item) {
queue = queue.then(item)
})
return queue;
}
// NOTE: pass FUNCTION not execed function.
queue([funcA, funcB, funcC, funcD])
.then((result) => console.log(`Finish ${result}`))
.catch(error => {
console.log(`Error: ${error}`);
})
}
function callInAsyncAwait() {
async function queue(arr) {
let res = []
for (let fn of arr) {
var data = await fn();
res.push(data);
}
return await res
}
// NOTE: pass FUNCTION not execed function.
queue([funcA, funcB, funcC, funcD])
.then((result) => console.log(`Finish ${result}`))
.catch(error => {
console.log(`Error: ${error}`);
})
}