Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Promise.all获得基于名称的结果的最佳es6方法_Javascript_Es6 Promise - Fatal编程技术网

Javascript 使用Promise.all获得基于名称的结果的最佳es6方法

Javascript 使用Promise.all获得基于名称的结果的最佳es6方法,javascript,es6-promise,Javascript,Es6 Promise,默认情况下,Promise.All([])函数返回一个基于数字的索引数组,其中包含每个Promise的结果 var promises = []; promises.push(myFuncAsync1()); //returns 1 promises.push(myFuncAsync1()); //returns 2 Promise.all(promises).then((results)=>{ //results = [0,1] } 用Promise.all()返回结果命名索引的

默认情况下,Promise.All([])函数返回一个基于数字的索引数组,其中包含每个Promise的结果

var promises = [];
promises.push(myFuncAsync1()); //returns 1
promises.push(myFuncAsync1()); //returns 2
Promise.all(promises).then((results)=>{
    //results = [0,1]
}
用Promise.all()返回结果命名索引的最佳方式是什么?

我尝试使用映射,但它以数组的方式返回结果:
[key1,value1,key2,value2]

更新:

我的问题似乎不清楚,以下是我不喜欢基于顺序的索引的原因:

  • 维护起来很糟糕:如果在代码中添加承诺,可能需要重写整个results函数,因为索引可能已更改
  • 读起来很糟糕
    结果[42]
    (可以通过下面jib的答案来解决)
  • 在动态环境中不可用
  • var承诺=[];
    如果(…)
    承诺。推动(…);
    否则{
    […]forEach(…=>{
    如果(…)
    承诺。推动(…);
    其他的
    […]forEach(…=>{
    承诺。推动(…);
    });
    });
    }
    承诺。所有(承诺)。然后((resultsArr)=>{
    /*在这里,我基本上是操没有明确的命名结果
    不依赖于数组中的承诺排序*/
    });
    
    就是这样吗

    var promises = [];
    promises.push(myFuncAsync1().then(r => ({name : "func1", result : r})));
    promises.push(myFuncAsync1().then(r => ({name : "func2", result : r})));
    Promise.all(promises).then(results => {
        var lookup = results.reduce((prev, curr) => {
            prev[curr.name] = curr.result;
            return prev;
        }, {});
        var firstResult = lookup["func1"];
        var secondResult = lookup["func2"];
    }
    

    ES6支持解构,因此如果您只想命名结果,可以编写:

    var myFuncAsync1=()=>Promise.resolve(1);
    var myFuncAsync2=()=>Promise.resolve(2);
    Promise.all([myFuncAsync1(),myFuncAsync2()]))
    。然后(([result1,result2])=>console.log(result1+”和“+result2))//1和2
    
    .catch(e=>console.error(e))一个很好的解决方案是使用异步等待。不像你说的ES6,而是ES8!但既然巴别塔完全支持它,我们就开始:

    通过使用
    async
    /
    wait
    ,可以避免只使用数组索引,如下所示

    async
    函数允许您在函数中使用
    await
    关键字,将其置于承诺之前,从而真正停止其中的代码。当
    async
    函数遇到尚未解析的承诺时,该函数立即返回一个挂起的承诺。此返回的承诺在函数稍后实际完成时立即解决。函数只有在解析之前等待的承诺时才会恢复,在此期间,它将把整个
    await promise
    语句解析为该承诺的返回值,允许您将其放入变量中。这有效地允许您在不阻塞线程的情况下暂停代码。一般来说,这是在JavaScript中处理异步内容的一种很好的方法,因为它使您的代码更按时间顺序排列,因此更易于推理:

    async function resolvePromiseObject(promiseObject) {
        await Promise.all(Object.values(promiseObject));
    
        const ret = {};
    
        for ([key, value] of Object.entries(promiseObject)) {
            // All these resolve instantly due to the previous await
            ret[key] = await value;
        };
    
        return ret;
    }
    

    与ES5以上版本一样:请确保正确配置了Babel,以便旧浏览器上的用户可以毫无问题地运行您的代码。只要您的babel配置正确,您就可以让async Wait在IE11上完美运行。

    关于@kragovip的答案,您想要避免的原因如下所示:

    “…等待所有网络和I/O呼叫非常容易

    但是,在一行中多次使用它时应该小心,因为wait关键字会停止它之后所有代码的执行。(与同步代码中的情况完全相同)

    坏榜样(不要效仿)

    他说:"此外,我们绝对毋须等待第一项要求完成,因为其他要求均不会因应结果而有所改变

    我们希望并行发送请求,并等待所有请求同时完成。这就是异步事件驱动编程的威力所在

    为了解决这个问题,我们可以使用Promise.all()方法。我们保存对变量的异步函数调用的承诺,将它们组合到一个数组中,然后立即等待它们。”

    相反

    async function processData() {
      const promise1 = downloadFromService1();
      const promise2 = downloadFromService2();
      const promise3 = downloadFromService3();
    
      const allResults = await Promise.all([promise1, promise2, promise3]);
    

    如果您不想修改结果对象的格式,这里有一个helper函数,它允许为每个条目指定一个名称,以便以后访问它

    const allNamed=(nameToPromise)=>{
    const entries=Object.entries(nameToPromise);
    return Promise.all(entries.map(e=>e[1]))
    。然后(结果=>{
    const nameToResult={};
    for(设i=0;i
    用法:

    var lookup=wait allNamed({
    rootStatus:fetch('https://stackoverflow.com/)。然后(rs=>rs.status),
    badRouteStatus:fetchhttps://stackoverflow.com/badRoute)。然后(rs=>rs.status),
    });
    var firstResult=lookup.rootStatus;//=200
    var secondResult=lookup.badRouteStatus;//=404
    

    如果您使用的是typescript,您甚至可以使用构造指定输入键和结果之间的关系:

    type ThenArg=T扩展PromiseLike?U:T;
    导出常量allNamed=<
    
    我不认为你能,也不应该?我假设“命名”是指具有键和值的对象,这些键是什么,您希望得到什么?许多库(如RSVP)都实现了散列方法。您可能需要另一个数组,如['myFuncAsync1','myFuncAsync2']。然后映射结果,比如Promise.all(promises).then((results)=>{var temp={};results.forEach((result,index)=>{temp[promisesNames[index]]]=result;});return temp;}。然后(result=>{})太糟糕了,它不像jQuery承诺那样可以执行$.when(refered1,refered2)。done(函数(result1,result2){…})你想用什么来“命名”你的结果(或它们的索引)?它应该发生在回调中还是承诺中?它需要动态命名吗?@spender它看起来更好,但这正是s
    async function processData() {
      const promise1 = downloadFromService1();
      const promise2 = downloadFromService2();
      const promise3 = downloadFromService3();
    
      const allResults = await Promise.all([promise1, promise2, promise3]);