初学者应该看的JavaScript Promise 完整指南( 四 )

在此示例中,我们读取文件1并将其写入output 文件 。稍后,我们读取文件2并将其再次附加到output文件 。如你所见,writeFile promise返回文件的内容,你可以在下一个then子句中使用它 。
如何链接多个条件承诺?你可能想要跳过 Promise 链上的特定步骤 。有两种方法可以做到这一点 。
const a = () => new Promise((resolve) => setTimeout(() => { console.log('a'), resolve() }, 1e3));const b = () => new Promise((resolve) => setTimeout(() => { console.log('b'), resolve() }, 2e3));const c = () => new Promise((resolve) => setTimeout(() => { console.log('c'), resolve() }, 3e3));const d = () => new Promise((resolve) => setTimeout(() => { console.log('d'), resolve() }, 4e3));const shouldExecA = true;const shouldExecB = false;const shouldExecC = false;const shouldExecD = true;Promise.resolve()  .then(() => shouldExecA && a())  .then(() => shouldExecB && b())  .then(() => shouldExecC && c())  .then(() => shouldExecD && d())  .then(() => console.log('done'))如果你运行该代码示例,你会注意到只有a和d被按预期执行 。
另一种方法是创建一个链,然后仅在以下情况下添加它们:
const chain = Promise.resolve();if (shouldExecA) chain = chain.then(a);if (shouldExecB) chain = chain.then(b);if (shouldExecC) chain = chain.then(c);if (shouldExecD) chain = chain.then(d);chain  .then(() => console.log('done'));如何限制并行 Promise?要做到这一点,我们需要以某种方式限制Promise.all 。
假设你有许多并发请求要执行 。如果使用 Promise.all 是不好的(特别是在API受到速率限制时) 。因此,我们需要一个方法来限制 Promise 个数,我们称其为promiseAllThrottled 。
// simulate 10 async tasks that takes 5 seconds to complete.const requests = Array(10)  .fill()  .map((_, i) => () => new Promise((resolve => setTimeout(() => { console.log(`exec'ing task #${i}`), resolve(`task #${i}`); }, 5000))));promiseAllThrottled(requests, { concurrency: 3 })  .then(console.log)  .catch(error => console.error('Oops something went wrong', error));输出应该是这样的:

初学者应该看的JavaScript Promise 完整指南

文章插图
 
以上代码将并发限制为并行执行的3个任务 。
实现promiseAllThrottled 一种方法是使用Promise.race来限制给定时间的活动任务数量 。
/** * Similar to Promise.all but a concurrency limit * * @param {Array} iterable Array of functions that returns a promise * @param {Object} concurrency max number of parallel promises running */function promiseAllThrottled(iterable, { concurrency = 3 } = {}) {  const promises = [];  function enqueue(current = 0, queue = []) {    // return if done    if (current === iterable.length) { return Promise.resolve(); }    // take one promise from collection    const promise = iterable[current];    const activatedPromise = promise();    // add promise to the final result array    promises.push(activatedPromise);    // add current activated promise to queue and remove it when done    const autoRemovePromise = activatedPromise.then(() => {      // remove promise from the queue when done      return queue.splice(queue.indexOf(autoRemovePromise), 1);    });    // add promise to the queue    queue.push(autoRemovePromise);    // if queue length >= concurrency, wait for one promise to finish before adding more.    const readyForMore = queue.length < concurrency ? Promise.resolve() : Promise.race(queue);    return readyForMore.then(() => enqueue(current + 1, queue));  }  return enqueue()    .then(() => Promise.all(promises));}


推荐阅读