xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

如何使用 js 实现一个 Promise.all 方法 PromiseAll All In One

如何使用 js 实现一个 Promise.all 方法 PromiseAll All In One

Promise

Promise.resolve()
Promise.reject()

const promise = new Promise();

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Promise.all

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

PromiseAll

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-08-0
 * @modified
 *
 * @description
 * @difficulty Easy Medium Hard
 * @complexity O(n)
 * @augments
 * @example
 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
 * @solutions
 *
 */

const log = console.log;

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 0, 'foo');
});
const promise4 = new Promise((resolve, reject) => {
  reject(`promise error`);
});

const promisesOK = [promise1, promise2, promise3];
const promisesError = [promise1, promise2, promise3, promise4];

const OK = Promise.all(promisesOK).then((values) => {
  log(`promisesOK values =`, values);
});


const Error = Promise.all(promisesError).then((values) => {
  log(`promisesError values =`, values);
}).catch(err => {
  log(`error =`, err)
});

setTimeout(() => {
  log(`\nOK =`, OK)
  log(`Error =`, Error)
}, 5);

/*

$ node promise.all.js

error = promise error
promisesOK values = [ 3, 42, 'foo' ]

OK = Promise { undefined }
Error = Promise { undefined }

*/


原理分析

Promise.resolve, Promise.reject

// Promise,不许需要用 Promise 包裹,但为了对齐也使用 Promise 包裹
promise1 = Promise.resolve(3);
// Promise {<fulfilled>: 3}

//  ✅ 未使用 Promise 包裹
promise1.then(v => console.log(v))
// 3
// Promise {<fulfilled>: undefined}
// ✅ 使用 Promise 包裹
Promise.resolve(promise1).then(v => console.log(v))
// 3
// Promise {<fulfilled>: undefined}

// 非 Promise,需要用 Promise 包裹
promise2 = 42;
// 42

// ❌ 未使用 Promise 包裹
promise2.then(v => console.log(v))
// Uncaught TypeError: promise2.then is not a function
// ✅ 使用 Promise 包裹
Promise.resolve(promise2).then(v => console.log(v))
// 42
// Promise {<fulfilled>: undefined}

// 异常 promise
promise4 = new Promise((resolve, reject) => {
  reject(`promise error`);
});
// Promise {<rejected>: "promise error"}

// ❌ 未使用 catch 处理
Promise.resolve(promise4).then(v => console.log(v))
// Promise {<rejected>: "promise error"}
// Uncaught (in promise) promise error Promise.then (async)
// ✅ 使用 catch 处理
Promise.resolve(promise4).then(v => console.log(v)).catch(err => console.log(`OK`))
// OK
// Promise {<fulfilled>: undefined}

// Promise.resolve, Promise.reject

solution

PromiseAll

// --unhandled-rejections=strict bug
/*

Unhandled promise rejection.
This error originated either by throwing inside of an async function without a catch block,
or by rejecting a promise which was not handled with .catch().
To terminate the node process on unhandled promise rejection,
use the CLI flag `--unhandled-rejections=strict`,
see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode

*/

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-08-14
 * @modified
 *
 * @description PromiseAll
 * @difficulty Easy Medium Hard
 * @complexity O(n)
 * @augments
 * @example
 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
 * @solutions
 *
 */

const log = console.log;

const PromiseAll = (promises = []) => {
  return new Promise((resolve, reject) => {
    let count = 0;
    const result = [];
    try {
      promises.forEach((promise) => {
        Promise.resolve(promise).then(value => {
          if(value) {
            count += 1;
            // promise order is not guaranteed /  顺序无法保证 ❌ push
            result.push(value)
          }
        }).catch(err => {
          throw new Error(err);
        });
      });
      if(count === promises.length) {
        log(`PromiseAll OK`)
        return resolve(result)
      }
    } catch (error) {
      log(`Promise Error`, error)
      throw new Error(error);
      // return reject(error);
    }
  }).catch(err => {
    log(`Promise Error`, err)
    return reject(error);
  });
}


https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-08-14
 * @modified
 *
 * @description PromiseAll
 * @difficulty Easy Medium Hard
 * @complexity O(n)
 * @augments
 * @example
 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
 * @solutions
 *
 */

const log = console.log;

const PromiseAll = (promises = []) => {
  let count = 0;
  const result = [];
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      Promise.resolve(promise).then(value => {
        if(value) {
          // promise order is guaranteed /  顺序可以保证 ✅ index
          result[count] = value;
          count += 1;
          // result.push(value)
        }
        // if(result.length === promises.length) {
        if(count === promises.length) {
          // log(`PromiseAll OK`, promises)
          resolve(result)
        }
      }, err => {
        reject(err);
      });
    });
  });
}

// test
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 0, 'foo');
});
const promise3 = 42;
// const promise2 = 42;
// const promise3 = new Promise((resolve, reject) => {
//   setTimeout(resolve, 0, 'foo');
// });
const promise4 = new Promise((resolve, reject) => {
  reject(`promise error`);
});

const promisesOK = [promise1, promise2, promise3];
const promisesError = [promise1, promise2, promise3, promise4];

const OK = PromiseAll(promisesOK).then((values) => {
  log(`promisesOK values =`, values);
});

// const OK = Promise.all(promisesOK).then((values) => {
//   log(`promisesOK values =`, values);
// });

const Error = PromiseAll(promisesError).then((values) => {
  log(`promisesError values =`, values);
}).catch(err => {
  log(`catch error =`, err)
});

// const Error = Promise.all(promisesError).then((values) => {
//   log(`promisesError values =`, values);
// }).catch(err => {
//   log(`error =`, err)
// });

setTimeout(() => {
  log(`\nOK =`, OK)
  log(`Error =`, Error)
}, 5);

/*

$ node promiseAll.js

error = promise error
promisesOK values = [ 3, 42, 'foo' ]

OK = Promise { undefined }
Error = Promise { undefined }

*/


/*
$ node PromiseAll.js ✅

catch error = promise error
promisesOK values = [ 3, 42, 'foo' ]

OK = Promise { undefined }

*/


PromiseAll OK ✅

async promise order OK ✅


"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2020-08-14
 * @modified
 *
 * @description PromiseAll
 * @difficulty Easy Medium Hard
 * @complexity O(n)
 * @augments
 * @example
 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
 * @solutions
 *
 */

const log = console.log;

const PromiseAll = (promises = [], debug = false) => {
  const result = [];
  return new Promise((resolve, reject) => {
    promises.forEach((promise, i) => {
      Promise.resolve(promise).then(value => {
        if(value) {
          // async promise order OK ✅
          result[i] = value;
          // async push order bug ❌
          // result.push(value)
        }
        if(result.length === promises.length) {
          if(debug) {
            log(`PromiseAll OK`, promises)
          }
          resolve(result)
        }
      }, err => {
        reject(err);
      });
    });
  });
}

// test
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 0, 'foo');
});
const promise3 = 42;
// const promise2 = 42;
// const promise3 = new Promise((resolve, reject) => {
//   setTimeout(resolve, 0, 'foo');
// });
const promise4 = new Promise((resolve, reject) => {
  reject(`promise error`);
});

const promisesOK = [promise1, promise2, promise3];
const promisesError = [promise1, promise2, promise3, promise4];

const OK = PromiseAll(promisesOK).then((values) => {
  log(`promisesOK values =`, values);
});

// const OK = Promise.all(promisesOK).then((values) => {
//   log(`promisesOK values =`, values);
// });

const Error = PromiseAll(promisesError).then((values) => {
  log(`promisesError values =`, values);
}).catch(err => {
  log(`catch error =`, err)
});

// const Error = Promise.all(promisesError).then((values) => {
//   log(`promisesError values =`, values);
// }).catch(err => {
//   log(`error =`, err)
// });

setTimeout(() => {
  log(`\nOK =`, OK)
  log(`Error =`, Error)
}, 5);


/*
$ node PromiseAll.js ✅

catch error = promise error
promisesOK values = [ 3, 'foo', 42 ]

OK = Promise { undefined }

*/

/*

$ node promise.all.js

error = promise error
promisesOK values = [ 3, 'foo', 42 ]

OK = Promise { undefined }
Error = Promise { undefined }

*/


refs

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2020-08-14 17:51  xgqfrms  阅读(1411)  评论(8编辑  收藏  举报