Javascript 试图定义一个承诺

Javascript 试图定义一个承诺,javascript,promise,es6-promise,Javascript,Promise,Es6 Promise,我试图通过创建本书练习中的Promise.all方法来理解承诺是如何工作的: 我尝试使用循环遍历作为方法本身参数提供的整个数组。然后,对于成功的承诺,处理程序主体将结果推送到我之前在循环外部定义的绑定,对于被拒绝的承诺,我使用。catch的方式是将被拒绝的值作为“原因”拒绝了主要的承诺,给了它一个错误 function Promise_all(promises) { return new Promise((resolve, reject) => { if(promises.l

我试图通过创建本书练习中的Promise.all方法来理解承诺是如何工作的:

我尝试使用循环遍历作为方法本身参数提供的整个数组。然后,对于成功的承诺,处理程序主体将结果推送到我之前在循环外部定义的绑定,对于被拒绝的承诺,我使用。catch的方式是将被拒绝的值作为“原因”拒绝了主要的承诺,给了它一个错误

function Promise_all(promises) {
  return new Promise((resolve, reject) => {
    if(promises.length == 0) resolve(promises);
    let fullArray = [];

    for(let i=0; i<promises.length ; i++){
         promises[i]
        .then(x => fullArray.push(x))
        .catch(reason => reject(new Error(reason)));
    }
    resolve(fullArray);
  });
}

正如@Bergi所说,代码的问题在于,.then“和.catch”回调是异步调用的,因此,在调用“resolve()”时甚至没有填充“fullArray”,即使它在循环之外也是如此。为了解决这个问题,我简单地在最后完成的承诺中添加了“resolve()”,为此,我简单地添加了一个“counter”绑定,该绑定的值等于“promises”数组的长度,并且每次减少1。然后对承诺调用“resolve()”,当这个“counter”等于0时,它调用“resolve()”

但这只解决了用承诺填充“fullArray”的问题,而不是那些承诺按调用顺序正确排序的问题,为了解决这个问题,我只是用循环的“i”绑定在数组中枚举它们,最终结果如下:

function Promise_all(promises) {
  return new Promise((resolve, reject) => {
    if(promises.length == 0) resolve(promises);
    let fullArray = [],
        counter = promises.length;

    for(let i=0; i< promises.length ; i++){
         promises[i]
        .then(x => {
           fullArray[i] = x;
           counter--;
           if(counter == 0) resolve(fullArray)})
        .catch(reason => reject(new Error(reason)));
    }
  });
}
功能承诺\u所有(承诺){
返回新承诺((解决、拒绝)=>{
如果(promissions.length==0)解析(promissions);
设fullArray=[],
计数器=长度;
for(设i=0;i<0.length;i++){
承诺[i]
.然后(x=>{
全数组[i]=x;
计数器--;
如果(计数器==0)解析(fullArray)})
.catch(原因=>拒绝(新错误(原因));
}
});
}

“解决承诺”-听起来你不清楚承诺会发生什么。你不能从外部“解决”或“强迫”它。承诺会自行解决,你所能做的就是倾听它。当承诺实际解决时,
then
catch
回调将始终异步调用。当您在循环之后立即调用
resolve()
时,您的
fullArray
实际上并没有被填充,因为循环只附加了处理程序,而没有等待任何操作。因此,如果我在数组中调用“resolve()”。那么“Promises”数组的最后一个promise中的“then”,则在“fullArray”被填充之前循环不会完成,对吗?是的,这是正确的想法。但不是数组中最后一个承诺的
then
回调,而是对最后发生的任何承诺的
then
回调。数组中的承诺可能在不同的时间实现,您希望等待所有承诺都实现。您需要一个计数器。还需要将
promises[i]更改为
Promise.resolve(promises[i])。然后()
以防在数组中传递不可接受的值(这是允许的)。我还建议使用
fullArray
而不是传递的
promises
数组来解析空值。
function Promise_all(promises) {
  return new Promise((resolve, reject) => {
    if(promises.length == 0) resolve(promises);
    let fullArray = [],
        counter = promises.length;

    for(let i=0; i< promises.length ; i++){
         promises[i]
        .then(x => {
           fullArray[i] = x;
           counter--;
           if(counter == 0) resolve(fullArray)})
        .catch(reason => reject(new Error(reason)));
    }
  });
}