Step-By-Step icon indicating copy to clipboard operation
Step-By-Step copied to clipboard

实现 Promise.race 方法

Open YvetteLau opened this issue 5 years ago • 13 comments

YvetteLau avatar Jun 17 '19 01:06 YvetteLau

差不多的把,和promise.all,只不过catch的话就要用setTime或者请求来触发reject

shenanheng avatar Jun 17 '19 06:06 shenanheng

哪个promise先被处理完,就返回哪个的结果,可以是reject也可以是resolve

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

测试代码

let promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 200, '100');
  })
let promise2 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, '200');
})
let promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 200, '300');
});

jodiezhang avatar Jun 17 '19 06:06 jodiezhang

const race = function (iterable) { return new Promise(function (resolve, reject) { for (const i in iterable) { const v = iterable[i] if (typeof v === 'object' && typeof v.then === 'function') { v.then(resolve, reject) } else { resolve(v) } } }) }

const p1 = new Promise(function (resolve) { setTimeout(resolve, 200, 1) }) const p2 = new Promise(function (resolve) { setTimeout(resolve, 100, 2) }) race([p1, p2]).then(function (res) { console.log(res) }) // 2

tianyuandsb avatar Jun 17 '19 07:06 tianyuandsb

Promise.race实现

Promise.race方法和Promise.all方法差不多,只是Promise.all需要等待所有的请求都完成,而Promise.race只要有一个请求完成就可以。 具体实现如下:

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

riluocanyang avatar Jun 17 '19 08:06 riluocanyang

Promise.race = function (promises) {
    if (!(promises instanceof Array))
      return reject("arguments must be an array");
    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
            return;
        } else {
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(data => {
                    return resolve(data);
                }, err => {
                    return reject(err);
                });
            }
        }
    });
}

into-piece avatar Jun 17 '19 11:06 into-piece

1.promise.race的实现

Promise.race = function(promiseArray) {
        return new Promise((res, rej) => {
          for (let i = 0; i < promiseArray.length; i++) {
            Promise.resolve(promiseArray[i]).then(
              function(value) {
                //成功
                return res(value);
              },
              function(error) {
                //失败
                return rej(error);
              }
            );
          }
        });
      };

2.测试

   let promise1 = new Promise((resolve, reject) => {
        setTimeout(resolve, 200, "promise1");
      });
      let promise2 = new Promise((resolve, reject) => {
        setTimeout(resolve, 1000, "promise2");
      });
      let promise3 = new Promise((res, rej) => {
        setTimeout(rej, 60, "fail");
      });
  Promise.race([promise1, promise2, promise3]).then(val => {
        console.log(val);
      });

sinaine avatar Jun 17 '19 11:06 sinaine

概念

Promise.race(iterable),当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象

应用场景

  1. 有些时候,多个异步任务是为了容错。比如,同时向两个URL读取用户的个人信息,只需要获得先返回的结果即可

代码实现

Promise.race = function (promises) {
	if (!Array.isArray(promises)) {
		throw new TypeError('You must pass array')
	}
	return Promise(function (resolve, reject) {
		function resolver(value) {
			resolve(value)
		}

		function rejecter(reason) {
			reject(reason)
		}
		for (var i = 0; i < promises.length; i++) {
			promises[i].then(resolver, rejecter)
		}
	})
}

测试

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, '2018');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, '2019');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // '2018' 因为2018更快
});

luohong123 avatar Jun 17 '19 14:06 luohong123

Promise.race 的实现

这边先说下Promise.race的几个注意点

  • Promise.race 用于将多个Promise对象包装成一个新的promise对象
  • 其状态由这多个promise对象中状态最先变为fullfilled 或rejected 的promise 对象决定
  • p的终值或拒因由最先变更状态的promise对象决定
Promise.race = arr => {
    return new Promise((resolve, reject) => {
      function myresolve(result) {
          resolve(result)
      }
      function myreject (error) {
          reject(error)
      }
      for (let i = 0;i <arr.length; i++ ) {
           arr[i].then(myresolve, myreject)
      }
    })
}

yelin1994 avatar Jun 17 '19 14:06 yelin1994

概念 Promise.all 返回的是传入的promise list 中每一单项调用之后的结果 Promise.race 返回的是传入的promise list 中最先返回的单项的调用结果 无论成功与否

实现

Promise.race= function(promises){
   if(!Array.isArray(promises)){
      throw  new Error('not a array')
   }
   return new Promise(function(resolve,reject){
        fucntion resolver(value){
          reslove(value)
       }
       function rejecter(value){
          reject(value)
       }
       for(var i=0;i<promises.length;i++){
           promises[i].then(resolver,rejecter)
       }
   })
}

测试

let p1 = new Promise(function(resolve,reject){
       setTimeout(function(){
        resolve('success')
       },1000)
})

let p2 = new Promise(function(resolve,reject){
       setTimeout(function(){
        resolve('faild')
       },500)
})

Promise.race([p1,p2]).then(result=>{
   console.log(result)             //  faild    faild耗时短
})

chongyangwang avatar Jun 18 '19 09:06 chongyangwang

在实现 Promise.race 方法之前,我们首先要知道 Promise.race 的功能和特点,因为在清楚了 Promise.race 功能和特点的情况下,我们才能进一步去写实现。

Promise.race 功能

Promise.race(iterable) 返回一个 promise,一旦 iterable 中的一个 promise 状态是 fulfilled / rejected ,那么 Promise.race 返回的 promise 状态是 fulfilled / rejected.

let p = Promise.race([p1, p2, p3]);

只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。

Promise.race 的特点

Promise.race 的返回值是一个 promise 实例

  • 如果传入的参数为空的可迭代对象,那么 Promise.race 返回的 promise 永远是 pending
  • 如果传入的参数中不包含任何 promisePromise.race 会返回一个处理中(pending)的 promise
  • 如果 iterable 包含一个或多个非 promise 值或已经解决的promise,则 Promise.race 将解析为 iterable 中找到的第一个值。

Promise.race 的实现

Promise.race = function (promises) {
    //promises传入的是可迭代对象(省略参数合法性判断)
    promises = Array.from(promises);//将可迭代对象转换为数组
    return new Promise((resolve, reject) => {
        if (promises.length === 0) {
            //空的可迭代对象;
            //用于在pending态
        } else {
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then((data) => {
                    resolve(data);
                }).catch((reason) => {
                    reject(reason);
                })
            }
        }
    });
}

YvetteLau avatar Jun 19 '19 14:06 YvetteLau

Promise.race = function(promises) {
    return new Promise(function(resolve, reject) {
        if (!promises || typeof promises[Symbol.iterator] !== 'function') {
            reject(TypeError());
        }
        for (let i = 0; i < promises.length; i++) {
            Promise.resolve(promises[i]).then(function(data) {
                resolve(data);
            }, function(error) {
                reject(error);
            });
        }
    });
}

AILINGANGEL avatar Jun 21 '19 08:06 AILINGANGEL

ღ( ´・ᴗ・` )比心

      const createPromise = (method) => {
        const promise = new Promise((resolve, reject) => {
          method(resolve, reject)
        })
        return promise
      }
      const race = (...tasks) => {
        tasks = tasks.flat()
        let tasksLength = tasks.length
        return createPromise((resolve, reject) => {
          let taskObj = {}
          Object.defineProperty(taskObj, '嘤嘤嘤', {
            set: ({
              type,
              data
            }) => {
              if (type === 'resolve') {
                resolve(data)
              } else {
                reject(data)
              }
            }
          })
          for (let step = 0, len = tasksLength; step < len; ++step) {
            const task = Promise.resolve(tasks[step])
            task.then(taskRes => {
              taskObj['嘤嘤嘤'] = {
                type: 'resolve',
                data: taskRes
              }
            }).catch(tashRej => {
              taskObj['嘤嘤嘤'] = {
                type: 'reject',
                data: tashRej
              }
            })
          }
        })
      }
      race([p1, p2, p3]).then(res => {
        console.log(res)
      }).catch(err => {
        console.log(err)
      })
      Promise.race([p1, p2, p3]).then(res => { 
        console.log(res)
      }).catch(err => {
        console.log(err)
      })

KRISACHAN avatar Jun 24 '19 06:06 KRISACHAN

Promise.nanlanRace = function (promises) {
    return new Promise(function (resolve, reject) {
        if (!(promises instanceof Array)) {
            return reject("params muse be Arrary");
        } else if (promises.length === 0) {
            //空的可迭代对象;
            //用于在pending态

        } else {
            for (let i = 0; i < promises.length; i++) {
                Promise.resolve(promises[i]).then(res => {
                    resolve(res);
                }, (err) => {
                    reject(err)
                })
            }
        }
    })
}

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, "one");
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 100, "two");
});

Promise.nanlanRace([p1, p2]).then(function (value) {
    console.log(value); // "two"
    // 两个都完成,但 p2 更快
});

MissNanLan avatar Jul 07 '19 11:07 MissNanLan