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

第 89 题:设计并实现 Promise.race() #140

Open
yygmind opened this issue Jun 12, 2019 · 24 comments
Open

第 89 题:设计并实现 Promise.race() #140

yygmind opened this issue Jun 12, 2019 · 24 comments
Labels

Comments

@yygmind
Copy link
Contributor

yygmind commented Jun 12, 2019

No description provided.

@lhyt
Copy link

lhyt commented Jun 12, 2019

Promise._race = promises => new Promise((resolve, reject) => {
	promises.forEach(promise => {
		promise.then(resolve, reject)
	})
})

@suki-chan
Copy link

Promise.myrace = function(iterator) {
    return new Promise ((resolve,reject) => {
        try {
            let it = iterator[Symbol.iterator]();
            while(true) {
                let res = it.next();
                console.log(res);
                if(res.done) break;
                if(res.value instanceof Promise) {
                    res.value.then(resolve,reject);
                } else {
                    resolve(res.value)
                }
                
            }
        } catch (error) {
            reject(error)
        }
    }) 
}

@CHristopherkeith
Copy link

基本和上面的例子差不多,不同点是每个传入值使用Promise.resolve转为Promise对象,兼容非Promise对象

const _race = (p)=>{
	return new Promise((resolve, reject)=>{
		p.forEach((item)=>{
			Promise.resolve(item).then(resolve, reject)
		})
	})
}

@Mini-Web
Copy link

Mini-Web commented Jul 19, 2019

Promise.miniRace = function(promises) {

    return new Promise((rs,rj)=>{
        try {
            // 检查输入值是否可迭代
            iteratorCheck(promises)

            const len = promises.length;
            let promiseStatusChanged = false;

            for (let i = 0; i < len; i++) {
                if (promiseStatusChanged)
                    break;
                // 使用 Promise.resolve 包装 thenable 和 非thenable 值
                Promise.resolve(promises[i]).then(rs).catch(rj).finally(()=>{
                    promiseStatusChanged = true
                }
                )
            }

        } catch (e) {
            rj(e)
        }

    }
    )
}

    function iteratorCheck(data) {
        if (!data[Symbol.iterator] || typeof data[Symbol.iterator] !== 'function') {
            const simpleType = typeof data;
            let errMsg = simpleType
            if (['number', 'boolean'].includes(simpleType) || data === null) {
                errMsg += ` ${String(data)}`
            }

            throw new TypeError(`${errMsg} is not iterable (cannot read property Symbol(Symbol.iterator))`)
        }
    }

@pre1ude
Copy link

pre1ude commented Jul 24, 2019

const PromiseRace = (iterable)=>{
    return new Promise((resolve, reject) => {
      for (const p of iterable) {
        Promise.resolve(p).then(resolve).catch(reject)
      }
    })
  }

@GoodLuckAlien
Copy link

 Promice.race= function(PromiseArr){
        let hasResolve = false
        return new PromiceA((resolve,reject)=>{
            PromiseArr.forEach(promiseItem=>{
                promiseItem.then(res=>{
                    !hasResolve && resolve(res)
                    hasResolve = true
                },(err)=>{
                   !hasResolve && reject(err)
                })
            })
        })
    }

@yaodongyi
Copy link

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 100)
})
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('failed')
    }, 500)
})

/**
 * 实现一个race
 * @param {Array} array 
 */
let race = function (array) {
    return new Promise((resolve, reject) => {
        let len = array.length;
        while (len--) {
            array[len].then(res => {
                return resolve(res);
            }).catch(err => {
                return reject(err);
            })
        }
    })
}
// 调用
race([p1, p2]).then(res => {
    console.log(res);
}).catch(err => {
    console.error(err);
})

@liyikun
Copy link

liyikun commented Oct 13, 2019

Promise._race = function(Promises) {
return new Promise((resolve, reject) => {
Promises.forEach(p => p.then(resolve, reject))
})
}

@aeolusheath
Copy link

Promise.race = function(...list) {
  return new Promise((resolve, reject) => {
    for (let item of list) {
      let p = item.then ? p : Promise.resolve(p) 
      // p.then(value => {
      //   resolve(value)
      // }).catch(err => {
      //   reject(err)
      // })
      p.then(resolve, reject)
    }
  })
}

@yygmind yygmind added the 异步 label Dec 16, 2019
@bbrucechen
Copy link

bbrucechen commented Dec 26, 2019

function promiseRace(promiseArr) {
  return new Promise((resolve,reject) => {
    for(let i = 0;i < promiseArr.length;i++) {
      promiseArr[i].then(res => resolve(res),rej => reject(rej))
    }
  })
}

const pro1 = new Promise((res,rej) => {
  setTimeout(() => {
    res('我是1')
  },1000)
})

const pro2 = new Promise((res,rej) => {
  setTimeout(() => {
    res('我是2')
  },10000)
})

const pro3 = new Promise((res,rej) => {
  setTimeout(() => {
    res('我是3')
  },300)
})

const race = promiseRace([pro1,pro2,pro3])
race.then(res => {
  console.log(res)
})

@jinfang12345
Copy link

let p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 100)
})
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('failed')
    }, 500)
})

/**
 * 实现一个race
 * @param {Array} array 
 */
let race = function (array) {
    return new Promise((resolve, reject) => {
        let len = array.length;
        while (len--) {
            array[len].then(res => {
                return resolve(res);
            }).catch(err => {
                return reject(err);
            })
        }
    })
}
// 调用
race([p1, p2]).then(res => {
    console.log(res);
}).catch(err => {
    console.error(err);
})

resolve()前 没必要return 吧

@random-yang
Copy link

function promiseRace(promises) {
    return new Promise((res, rej) => {
        promises.forEach(promise => promise.then(res).catch(rej));
    })
}

@xiaochen-01
Copy link

xiaochen-01 commented Apr 22, 2020

Promise.protopype.race = (promises) => {
    return new Promise((resolve, reject) => {
        promises.forEach(promise => promise.then(resolve, reject))
    });
}

@tjwyz
Copy link

tjwyz commented Jul 16, 2020

	static race(arr) {
		// 只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。
		return new PromiseA((resolve, reject) => {
			arr.forEach((item)=>{
				// “状态的变更是单向的”
				item.then(resolve, reject);
			})
		})
	}

@wang-qiqi
Copy link

有点像电路的并行,只要有一个开关打开的就可以接通了。

@chun1hao
Copy link

Promise.race = function(promises){
    return new Promise((resolve, reject)=>{
        for(let i of promises){
            Promise.resolve(i).then(resolve, reject)
        }
    })    
}

@slogeor
Copy link

slogeor commented Oct 24, 2020

function testRace() {
    function getPromise(i, timeout = 0) {
        const random = Math.random();
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                random > 0.5 ? reject(`reject: ${random} - ${i}`) : resolve(`resolve: ${random} - ${i}`)
            }, timeout)
        })
    }

   
    Promise.race2 = function (promises) {
        return new Promise((resolve, reject) => {
            for (let i = 0; i < promises.length; i++) {
                // promises[i] 可能是普通值
                Promise.resolve(promises[i]).then((data) => {
                    resolve(data);
                }, (err) => {
                    reject(err)
                });
            }
        });
    }


    const p1 = getPromise(1, 200);
    const p2 = getPromise(2, 300);
    const p3 = getPromise(3, 100);

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

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

testRace();

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

可以通过设置 getPromise 函数的第二个参数,验证race2 输出结果与 race是否一致

@ghost
Copy link

ghost commented Feb 24, 2021

Promise._race = function(iterator) {
            return new Promise((resolve, reject) => {
                for (let item of iterator) {
                    Promise.resolve(item).then((data) => {
                        resolve(data);
                    }).catch(err => {
                        reject(err);
                    });
                }
            });
        }

@jackluson
Copy link

Tip:

  1. Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝
  1. 判断函数参数是否是可迭代的(很多答案都忽略了)
const isIterable = (data, reject) => {
  const type = typeof data;
  if (!data[Symbol.iterator]) {
    if (reject) {
      reject(
        new TypeError(
          `${type} ${data} is not iterable (cannot read property Symbol(Symbol.iterator))`
        )
      );
    } else {
      throw new TypeError(
        `${type} ${data} is not iterable (cannot read property Symbol(Symbol.iterator))`
      );
    }
  }
};
Promise.myRace = function (promises) {
  return new Promise((resolve, reject) => {
    isIterable(promises, reject); // 判断是否是迭代对象
    const promiseArray = [...promises];
    promiseArray.forEach((pr) => {
      if (!(pr instanceof Promise)) {
        pr = Promise.resolve(pr);
      }
      pr.then(resolve, reject);
    });
  });
};

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "one");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, "two");
});

Promise.myRace([promise1, promise2])
  .then((value) => {
    console.log("value", value);
    // Both resolve, but promise2 is faster
  })
  .catch((err) => {
    console.log("err", err);
  });

@PastelSubliminal
Copy link

Promise.race = function(values){
  return new Promise((resolve,reject)=>{
    for(let i = 0 ; i< values.length;i++){
      Promise.resolve(values[i]).then(resolve,reject)
    }
  })
}

@Yangfan2016
Copy link

Promise.race = function (proms) {
    return new Promise((rs, rj) => {
        proms.forEach(p => {
            Promise.resolve(p).then(rs).catch(rj);
        })
    });
}

@lastertd
Copy link

lastertd commented Sep 6, 2023

    static race<T extends Iterable<any>>(args: T) {     //约定T从属于Iterable类型
        return new MyPromise((resolve, reject) => {
            const promise = Array.from(args);   //将args转化为数组类型
            if (promise.length === 0){      //假设数组长度为0, 则永远处于pending状态
                return
            }
            /**会执行所有resolve或者reject,
             * 但是Promise内部状态只会变化一次(pending->fulfilled | pending->rejected)
             * 所以只会保留第一次状态改变
             */
            for (let i = 0; i < promise.length; i++) {
           //用Promise.resolve包裹一层, 可以将非Promise对象转为Promise对象
                MyPromise.resolve(promise[i]).then(data => {
                    resolve(data);
                },reason => {
                    reject(reason)
                })
            }
        })
    }

@Dylan0916
Copy link

Promise.myRace = (promises) => {
  const _promises = Array.isArray(_promises) ? _promises : [promises];

  return new Promise((resolve, reject) => {
    _promises.forEach((promise) => {
      Promise.resolve(promise).then(resolve, reject);
    });
  });
};

@negativeentropy9
Copy link

Promise.fakeRace = function (list) {
  return new Promise((resolve, reject) => {
    list.forEach((promise) => {
      promise.then(resolve, reject);
    });
  });
};

function createPromise(i) {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      // resolve(i);
      reject(i);
      clearTimeout(timer);
    }, i * 100);
  });
}

Promise.fakeRace([createPromise(1), createPromise(2)]).then(
  (data) => console.log("fullfilled", data),
  (e) => console.log("rejected", e)
);

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

No branches or pull requests