Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1. 实现一个Promise.all #1

Open
Sunny-117 opened this issue Nov 3, 2022 · 22 comments
Open

1. 实现一个Promise.all #1

Sunny-117 opened this issue Nov 3, 2022 · 22 comments

Comments

@Sunny-117
Copy link
Owner

No description provided.

@Sunny-117
Copy link
Owner Author

/**
   * 得到一个新的Promise,该Promise的状态取决于proms的执行
   * proms是一个迭代器,包含多个Promise
   * 全部Promise成功,返回的Promise才成功,数据为所有Primsise成功的数据,并且顺序时按照传入的顺序排列
   * 只要有一个Promise失败,则=返回的Pormise失败,原因是第一个Promise失败的原因
   * @param {iterator} proms
   */
  Promise.all=function (proms) {
    return new MyPromise((resolve, reject) => {
      try {
        const results = []; //接受每个Promise成功后的结果
        let count = 0; // Promse计数总数
        let fulfilledCount = 0; // 已完成的数量
        for (const p of proms) {
          // resolve([1,2,3,4])
          // 思考:如何保证数组是有序的?如何知道啥时候所有promise都完成?
          let i = count; // 保存一下当前下标
          count++;

          /**
           * 先包一下p,处理有直接写数字的情况
           */
          MyPromise.resolve(p).then((data) => {
            //异步,代码运行到这里,循环就已经结束了,因为在微队列
            fulfilledCount++;
            // console.log(i);
            results[i] = data;
            // results.push(data);不能用push
            console.log(fulfilledCount);
            if (fulfilledCount === count) {
              // 当前是最后一个Promise完成了
              console.log("全部完成");
              resolve(results);
            }
          }, reject);
        }
        console.log(count, fulfilledCount);
        /**
         * 特殊情况1:传递空数组
         */
        if (count === 0) {
          resolve(results);
        }
      } catch (error) {
        reject(error);
        console.error(error);
      }

      /**
       * 特殊情况2:执行中报错:try,catch
       */
    });
  }
  
  
  /*******test all *******/
  
/**
 * 不仅可以传数组,还可以传递迭代器。不是所有迭代器都支持for循环,所以。。。
 */
Promise.all([
  MyPromise.reject(1),
  MyPromise.resolve(2),
  MyPromise.resolve(3),
  4,
]).then(
  (data) => {
    // data:[1,2,3,4]
    // 传递[pro1,pro2,pro3,4]的话:内部默认处理Promise.resolve(4)
    console.log("成功", data);
  },
  (reason) => {
    // reason:reason2
    console.log("失败", reason);
  }
);

@CwRv07
Copy link
Contributor

CwRv07 commented Nov 21, 2022

Promise._all = function (promises) {
  // 该方法返回一个promise对象
  return new Promise((resolve, reject) => {
    // 该方法的参数需为一个可迭代对象
    if (promises == null || typeof promises[Symbol.iterator] !== "function") {
      throw new TypeError(`${promises} is not a iterable`);
    }
    promises = [...promises];

    // 可迭代对象为空则返回已resolve的promise
    if (promises.length === 0) {
      resolve([]);
    }

    let count = 0;
    const values = [];
    promises.forEach((promise, index) => {
      // 保证可迭代对象的元素为promise,使用Promise.resolve()处理
      Promise.resolve(promise)
        .then((res) => {
          values[index] = res;
          if (++count === promises.length) resolve(values);
        })
        .catch(reject);
    });
  });
};

@veneno-o
Copy link
Contributor

Promise._all = (iterObj) => {
    // 1. iterObj 必须是一个可迭代对象, 否则, 无法正常进行则抛出错误
    if(!(typeof iterObj === "object" && iterObj !== null && typeof iterObj[Symbol.iterator] === "function")){
        throw new TypeError(`${iterObj} is not iterable`);
    }
    iterObj = [...iterObj];
    /*
     *  2. 函数返回值为 `<Promise>` 对象, 当参数 `iterObj` 内所有的 `Promise` 成功, 
     *     该 `<Promise>` 对象成功, 成功数据为所有成功的 `Promise` 结果数组,
     *     有一个不成功, 则该 `<Promise>` 不成功, 失败数据为失败原因字符串
     */
    return new Promise((resolve, reject) => {
        const len = iterObj.length;
        let count = 0;
        if(len === 0) return resolve([]);

        const res = new Array(len);
        iterObj.forEach(async (item, index) => {
            const newItem = Promise.resolve(item);
            try{
                const result = await newItem;
                res[index] = result;
                if(++count === len){
                    resolve(res)
                }
            }catch(err){
                reject(err);
            }
        })
    })
}

// 验证:
function test(){
    try{
        Promise._all(null).then(res=>console.log(res), rej=>console.log(rej)); 
        // throw err: null is not iterable
    }catch(e){
        console.log(e)
    }

    try{
        Promise._all({}).then(res=>console.log(res), rej=>console.log(rej)); 
        // throw err: [object object] is not iterable
    }catch(e){
        console.log(e)
    }
    
    Promise._all([]).then(res=>console.log(res), rej=>console.log(rej)); 
    // []
    
    Promise._all(new Set()).then(res=>console.log(res), rej=>console.log(rej)); 
    // []
    
    Promise._all(new Map()).then(res=>console.log(res), rej=>console.log(rej)); 
    // []
    
    Promise._all([
        Promise.resolve(1),
        Promise.resolve(2),
        Promise.resolve(3),
        4,
      ]).then(res=>console.log(res), rej=>console.log(rej))
    
    // [1, 2, 3, 4]
    
    Promise._all([
        Promise.reject(1),
        Promise.resolve(2),
        Promise.resolve(3),
        4,
      ]).then(res=>console.log(res), rej=>console.log(rej))
    // 1
}
test();

@Pcjmy
Copy link
Contributor

Pcjmy commented Jan 23, 2023

Promise.myAll = (promises) => {
    return new Promise((resolve, reject) => {
        let count = 0
        let result = []
        const len = promises.length
        if (len === 0) {
            return resolve([])
        }

        promises.forEach((p, i) => {
            Promise.resolve(p).then((res) => {
                count += 1
                result[i]=res
                if(count === len) {
                    resolve(result)
                }
            }).catch(reject)
        })
    })
}

@bearki99
Copy link

bearki99 commented Feb 1, 2023

Promise.myAll = (promises) => {
  return new Promise((resolve, reject) => {
    let idx = 0;
    const ans = [];
    promises.forEach((item, index) => {
      Promise.resolve(item).then(
        (res) => {
          ans[index] = res;
          idx++;
          if (idx === promises.length) {
            resolve(ans);
          }
        },
        (err) => reject(err)
      );
    });
  });
};

@jlx2002
Copy link
Contributor

jlx2002 commented Feb 2, 2023

Promise._all = function (promiseList) {
  return new Promise((resolve, reject) => {
    // 如果传入的参数 不是数组
    if (!Array.isArray(promiseList)) {
      return reject(new Error("传入的参数不是数组!"));
    }

    const res = [];
    let counter = 0; // 设置一个计数器
    for (let i = 0; i < promiseList.length; i++) {
      Promise.resolve(promiseList[i])
        .then((val) => {
          counter++;
          res[i] = val; // 返回值
          if (counter == promiseList.length) {
            resolve(res);
          }
        })
        .catch((e) => reject(e));
    }
  });
};

@Stream-web
Copy link
Contributor

function promiseAll(promises) {
    return new Promise(function(resolve, reject) {
      if(!Array.isArray(promises)){
          throw new TypeError(`argument must be a array`)
      }
      var resolvedCounter = 0;
      var promiseNum = promises.length;
      var resolvedResult = [];
      for (let i = 0; i < promiseNum; i++) {
        Promise.resolve(promises[i]).then(value=>{
          resolvedCounter++;
          resolvedResult[i] = value;
          if (resolvedCounter == promiseNum) {
              return resolve(resolvedResult)
            }
        },error=>{
          return reject(error)
        })
      }
    })
  }

@sv-98-maxin
Copy link

Promise.myAll = promises => {
  // 参数需要是一个可迭代对象
  if(typeof promises[Symbol.iterator] !== 'function'){
    throw(`${promises}不是一个可迭代对象`)
  }
  promises = [...promises]
  const len = promises.length,
        result = []; //存放结果
  let count = 0 //promise完成的个数
  if(len === 0){
    // 直接返回一个promise包装的数组
    return Promise.resolve([])
  }
  return new Promise((resolve, reject) => {
    promises.forEach((pr, idx) => {
      // 确保每一项都是promise
      Promise.resolve(pr).then(res => {
        result[idx] = res
        count++
        if(count === len){
          return resolve(result)
        }
      }).catch(e => {
        reject(e)
      })
    })
  })
}

@coffeeAndTeaa
Copy link

Promise.myAll = function (iterObj) {
  //1. 检查arr是否是可迭代的对象
  if (
    !(
      typeof iterObj === "object" &&
      iterObj !== null &&
      typeof iterObj[Symbol.iterator] === "function"
    )
  ) {
    throw new Error(`${iterObj} is not iterable`);
  }

  iterObj = [...iterObj];
  // 创造一个新的promise
  return new Promise((resolve, reject) => {
    const results = [];
    let count = 0;
    let finished = 0;

    for (let p of iterObj) {
      let index = count;
      count++;
      // 如果传入的p不是promise直接resolve
      // 到这一步时所有的for loop 已经结束
      Promise.resolve(p).then(
        (res) => {
          finished++;
          results[index] = res;
          if (finished === count) {
            resolve(results);
          }
        },
        (rej) => {
          reject(rej);
        }
      );
    }
  });
};

p1 = Promise.resolve(1);
p2 = new Promise((res, rej) => {
  setTimeout(() => {
    res(2);
  }, 1000);
});
p3 = new Promise((res, rej) => {
  setTimeout(() => {
    res(3);
  });
});

const arr = [];
arr.push(p1);
arr.push(p2);
arr.push(p3);

Promise.myAll(arr).then((res) => {
  console.log(res);
});

@kangkang123269
Copy link

kangkang123269 commented Feb 20, 2023

function myPromiseAll(promises) {
  // 检查是否是迭代对象
  if(typeof promises[Symbol.iterator] !== 'function') {
      throw(`传入的参数不是一个可迭代对象`)
  }
  return new Promise((resolve, reject) => {
    const results = [];
    let count = 0;

    promises.forEach((promise, index) => {
      Promise.resolve(promise)
        .then(result => {
          results[index] = result;
          count++;
          if (count === promises.length) {
            resolve(results);
          }
        })
        .catch(error => {
          reject(error);
        });
    });
  });
}

@sunshineLixun
Copy link

class MyPromise {
  static all(promise) {
    if (
      !(
        typeof promise === "object" &&
        promise !== null &&
        typeof promise[Symbol.iterator] === "function"
      )
    ) {
      throw new Error(`${promise} is not iterator`);
    }

    return new Promise((resolve, reject) => {
      const length = promise.length;
      if (length === 0) {
        resolve([]);
      }

      const results = [];
      let idx = 0;
      promise.forEach((promise, index) => {
        Promise.resolve(promise)
          .then((res) => {
            idx++;
            // 返回值跟传入的promise一一对应
            results[index] = res;
            // 确保所有promise都执行完成
            if (idx === length) {
              resolve(results);
            }
          })
          .catch((error) => {
            reject(error);
          });
      });
    });
  }
}

function test() {
  try {
    MyPromise.all(1)
      .then((res) => console.log(res))
      .catch((err) => console.log("reject", err));
  } catch (error) {
    console.log("catch", error);
  }

  try {
    MyPromise.all({})
      .then((res) => console.log(res))
      .catch((err) => console.log("reject", err));
  } catch (error) {
    console.log("catch", error);
  }

  try {
    MyPromise.all([])
      .then((res) => console.log("success", res))
      .catch((err) => console.log("reject", err));
  } catch (error) {
    console.log("catch", error);
  }

  MyPromise.all([Promise.resolve(1), {}])
    .then((res) => console.log("success", res))
    .catch((err) => console.log("reject", err));

  MyPromise.all([Promise.reject("12312321"), Promise.resolve(123)])
    .then((res) => console.log("success", res))
    .catch((err) => console.log("reject", err));
}

test();

@YMnotafraid
Copy link

Promise.myall = (promises) => {
  //判断当前数据能否迭代
  if (
    !(
      typeof promises === "object" &&
      promises !== null &&
      typeof promises[Symbol.iterator] === "function"
    )
  ) {
    throw new TypeError(`${promises} is not iterable`);
  }
  promises = [...promises];
  return new Promise((resolve, reject) => {
    const len = promises.length;
    if (len === 0) return resolve([]);
    const ans = [];
    let cnt = 0;
    promises.forEach(async (promise) => {
      try {
        const res = await promise;
        ans.push(res);
        //当所有promise对象都成功时返回成功的promise对象
        if (++cnt === len) resolve(ans);
      } catch (error) {
        //当出现失败的promise对象时立刻返回错误的原因error
        reject(error);
      }
    });
  });
};

//test
try {
  Promise.myall({}).then(
    (res) => console.log(res),
    (rej) => console.log(rej)
  ); //TypeError: [object Object] is not iterable
} catch (error) {
  console.log(error);
}

Promise.myall([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3),
  4,
]).then(
  (res) => console.log(res), //[ 1, 2, 3, 4 ]
  (rej) => console.log(rej)
);
Promise.myall([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(3),
  4,
]).then(
  (res) => console.log(res),
  (rej) => console.log(rej) // 3
);

Promise.myall([
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.reject(3).catch((err) => console.log(err)), //3
  4,
]).then(
  (res) => console.log(res), //[ 1, 2, 4, undefined ]
  (rej) => console.log(rej)
);

@xun-zi
Copy link

xun-zi commented Mar 13, 2023

/**
       * 得到一个新的Promise,该Promise的状态取决于proms的执行
       * proms是一个迭代器,包含多个Promise
       * 全部Promise成功,返回的Promise才成功,数据为所有Primsise成功的数据,并且顺序时按照传入的顺序排列
       * 只要有一个Promise失败,则=返回的Pormise失败,原因是第一个Promise失败的原因
       * @param {iterator} proms
       */

    function PromiseAll(proms) {
        return new Promise((resolve, reject) => {
            let fulfilledCount = 0;
            const res = [];
            proms.forEach((p, index) => {
                p.then((val) => {
                    fulfilledCount++;
                    res[index] = val;
                    if (fulfilledCount == proms.length) resolve(res);
                }, reject)
            })
        })
    }
    // const p1 = Promise.resolve('p1')
    // const p2 = new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         resolve('p2 延时一秒')
    //     }, 1000)
    // })

    // const p3 = new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         resolve('p3 延时两秒')
    //     }, 2000)
    // })

    // const p4 = Promise.reject('p4 rejected')

    // const p5 = new Promise((resolve, reject) => {
    //     setTimeout(() => {
    //         reject('p5 rejected 延时1.5秒')
    //     }, 1500)
    // })

    //成功
    // const res1 = PromiseAll([p1, p2, p3])
    // res1.then(val => console.log('res1', val),val => console.error(res1,val))
    // 一个失败
    // const res2 = PromiseAll([p1, p2, p4])
    // res2.then(val => console.log('res2', val),val => console.error(res2,val))
    //一个延时失败
    // const res3 = PromiseAll([p1, p2, p5])
    // res3.then(val => console.log('res3', val), val => console.error('res3', val))
    //两个失败
    // const res4 = PromiseAll([p1, p4, p5])
    // res4.then(val => console.log('res4', val), val => console.error('res4', val));

@DULANGHAI
Copy link

Promise.all = function(promises) {
  return new Promise((resolve, reject) => {
    let result = [];
    let len = promises.length;
    if(len === 0) {
      resolve(result);
      return;
    }
    const handleData = (data, index) => {
      result[index] = data;
      // 最后一个 promise 执行完
      if(index == len - 1) resolve(result);
    }
    for(let i = 0; i < len; i++) {
      // 为什么不直接 promise[i].then, 因为promise[i]可能不是一个promise
      Promise.resolve(promise[i]).then(data => {
        handleData(data, i);
      }).catch(err => {
        reject(err);
      })
    }
  })
}

@cscty
Copy link

cscty commented Jun 12, 2023

Promise.All = function(props) {
if(props.length === 0) Promise.resolve([])
return new Promise((resolve,reject)=>{
const result = []
for(let i = 0;i<props.length;i++) {
Promise.resolve(props[i]).then((data) =>{
result[i] = data
if (i === props.length-1) {
resolve(result)
}
}, reject)
}
})
}低配版

@cscty
Copy link

cscty commented Jun 12, 2023

Promise.All = function(props) {
                if(props.length === 0) Promise.resolve([])
                return new Promise((resolve,reject)=>{ 
                    const result = []
                    for(let i = 0;i<props.length;i++) {
                        Promise.resolve(props[i]).then((data) =>{
                            result[i] = data
                            if (i === props.length-1) {
                                resolve(result)
                            }
                        }, reject)
                    }
                })
            }``

@cscty
Copy link

cscty commented Jun 18, 2023

Promise.All = function (ites) {
let result = [];
// 什么时候结束
let count = 0;
return new Promise((res, rej) => {
ites.forEach((val, i) => {
Promise.resolve(val).then((data) => {
res[i] = val;
count++;
if (count === ites.length) {
res(result);
}
}, rej);
});
});
};

@why-ztc
Copy link

why-ztc commented Jun 20, 2023

Promise.all = function (list) {
  const result = []
  let count = 0
  return new Promise((resolve, reject) => {
    list.forEach((item, i) => {
      Promise.resolve(item).then(res => {
        result[i] = res
        count++
      }).catch(err => {
        reject(err)
      })
    })
    if (count === list.length) {
      resolve(result)
    }
  })
}

@Simonduya
Copy link

 // promise.all会返回一个新的promise,当promise数组中所有的promise都成功才resolve, 而只要其中一个失败就直接reject失败的结果
      const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(111);
        }, 2000);
      });
      const p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(222);
        }, 1000);
      });
      const p3 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(333);
        }, 3000);
      });

      Promise.all([p1, p2, p3]).then(
        (res) => {
          console.log(res);
        },
        (err) => {
          console.log(err);
        }
      );

      Promise._all = function (promises) {
        return new Promise((resolve, reject) => {
          let results = [];
          promises.forEach((promise, index) => {
            promise.then(
              (res) => {
                // 加个索引就可以知道是哪个promise的结果
                results.push({ res, index });
                if (results.length === promises.length) {
                  resolve(results);
                }
              },
              (err) => {
                reject(err);
              }
            );
          });
        });
      };

      Promise._all([p1, p2, p3]).then(
        (res) => {
          console.log(res);
        },
        (err) => {
          console.log(err);
        }
      );

@why-ztc
Copy link

why-ztc commented Aug 11, 2023

Promise.all = function (...args) {
  return new Promise((resolve, reject) => {
    try {
      const result = []
      let count = 0
      const len = args.length
      args.forEach((item, i) => {
        Promise.resolve(item).then(res => {
          result[i] = res
          count++
          if (len === count) {
            resolve(result)
          }
        }).catch((err) => {
          reject(err)
        })
      })
    } catch (error) {
      reject(error)
    }
  })
}

@ruxin23
Copy link

ruxin23 commented Oct 30, 2023

Promise.myAll = function (promises) {
    return new Promise((resolve, reject) => {
        const result = []
        let count = 0
        if (promises.length === 0) return resolve([])
        promises.forEach((p, index) => {
            Promise.resolve(p).then(res => {
                result[index] = res
                count++
                if (count === promises.length) {
                    resolve(result)
                }
            }).catch(err => {
                reject(err)
            })
        })
    })
}

@stryear
Copy link

stryear commented Jul 1, 2024

/**
 * @description promiseAll函数接受一个数组,数组中的元素都是Promise对象,
 * 返回一个Promise对象,这个Promise对象在数组中所有Promise对象都成功时才成功,否则失败。
 */
function promiseAll<T>(promises: Promise<T>[]): Promise<T[]> {
    return new Promise((resolve, reject) => {
        // 检查promises是否为数组
        if (!Array.isArray(promises)) {
            return reject(new TypeError('promises must be an array'))
        }
        let resolvedCount = 0;
        const promiseNum = promises.length;
        const resolvedValues = new Array<T>(promiseNum);
        // 遍历promises数组,将每个Promise对象转换为Promise.resolve(),
        // 然后通过then()方法处理结果
        for (let i = 0; i < promiseNum; i++) {
            Promise.resolve(promises[i]).then(value => {
                resolvedCount++;
                resolvedValues[i] = value;
                if (resolvedCount === promiseNum) {
                    resolve(resolvedValues);
                }
            }, reject);
        }
        if (promiseNum === 0) {
            resolve(resolvedValues);
        }
    });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests