javascript - promise.all 嵌套无法保证内层的Promise执行顺序

查看:209
本文介绍了javascript - promise.all 嵌套无法保证内层的Promise执行顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

1、使用nodejs,外层有var enter = Promise.all([Promise.all([innerPromise...])...]).then(console.log("problem happend"))嵌套来解析二维数据,内层的数组的innerPromise实际上也是一个startPromise.then(return secendPromise)结构。结果secendPromise在外层Promise.all Fulfilled后才执行. 即problem happend 会在secendPromise还未执行时就已经输出了。难道Promise.all不是promise数组都Fulfilled了之后才会被Fulfilled?

2、具体的示例如下。输入数据型如[[cat,[nameId1,nameId2,nameId3...]]...],cat对应多个nameId。这种二维数据使用了两个Promise.all嵌套解析。执行结果是数据库操作的第一步insertCategoryAttrName完成后client就关闭了,后续的查询和插入操作无法完成。

function dbInsert(catAttrMap,client){
    var taskArray = Array.from(catAttrMap);
    //外层的数组使用Promise.all
    var promiseArray = taskArray.map(function(value,index){
        var categoryId = value[0];
        var attibuteNameIdPromiseArray = Array.from(value[1]);
        attibuteNameIdPromiseArray.map(function(attrinameId,sortValue){
            //Promise数据操作链
            return insertChain(categoryId,attrinameId,sortValue)
        })
        //内层set使用一个Promise.all全部满足后
        return Promise.all(attibuteNameIdPromiseArray);
    })
    return  Promise.all(promiseArray).finally(function(){
            client.end(); //数据库资源释放
    });
}

/*
* 数据库异步操作链 
* 1、insertCategoryAttrName 插入数据库后返回categoryId,
* 2、随后getAttributeValuesByNameId查询数据库获取attriValueId数组
* 3、根据categoryId,attriValueId插入数据库
*/
function insertChain(categoyId,attrinameId,sortValue){
    return insertCategoryAttrName(categoyId,attrinameId,sortValue,"1")
           .then(function(cateAttNameId){
                attributeCounter++;
                return getAttributeValuesByNameId(attrinameId).then(function(attriValueIdObjectArray){
                    console.log("属性value组大小:" + attriValueIdObjectArray.length);
                    var attributeInsertPromiseArr = attriValueIdObjectArray.map(function(attributeIdObject,index){
                        return insertCategoryAttrValue(cateAttNameId,attributeIdObject.id,index).then(function(){
                            valueCounter++;
                        });
                    })
                    return Promise.all(attributeInsertPromiseArr);
                });
            }).then(function(){
                console.log("right time?")
            })
}

function insertCategoryAttrName(args..){
    return new Promise(..)
}

function getAttributeValuesByNameId(args..){
    return new Promise(..)
}

function insertCategoryAttrValue(args..){
    return new Promise(..)
}

3、我这边怀疑和Promise.all的机制有关系,于是把dbInsert的二维数组展开成一维数组,使用一层Promise.all发现client可以在合适的时机关闭

/**
*  首先根据属性Set展开。使整个cate-attributeName的数组扁平
*/

function dbInsertPlain(catAttrMap){
    var taskArray = Array.from(catAttrMap);
    console.log("category大小"+ taskArray.length);
    var skretch = new Array();

    taskArray.forEach(function(currentValue){
        var categoryId = currentValue[0];
        var nameIdArray = Array.from(currentValue[1]);
        nameIdArray.forEach(function(value,index){
            skretch.push([categoryId,value,index])
        })
    })

    var promiseArray = skretch.map(function(value,index){
        let categoryId = value[0];
        let attrinameId = value[1];
        let sortValue = value[2];
        return insertChain(categoryId,attrinameId,sortValue)
    })
    //使用展开后的Promise.all
    return  Promise.all(promiseArray).finally(function(){
        client.end();
    });
}

4 、因此基本可以判断是Promise.all nest导致对insertCategoryAttrName后面then执行状态的感知。具体的原因仍然想不明白,求高手指点。

5、本地用setTimeout模拟场景做了下测试..好吧,代码书写问题..insertChain方法内层的Promise.all根本就没返回..不过借这个机会看了Promise的源码也算是收获

var *attibuteNameIdArray* = Array.from(value[1]);
var *attibuteNameIdPromiseArray* = *attibuteNameIdArray*.map(function(attrinameId,sortValue){
            //Promise数据操作链
            return insertChain(categoryId,attrinameId,sortValue)
        })
         //内层set使用一个Promise.all全部满足后
        return Promise.all(*attibuteNameIdPromiseArray*);

解决方案

模拟代码

这个是本地测试的代码,有兴趣可以看下执行的情况,Promise用的bluebird,需要先npm 安装下依赖。

请输入代码var Promise = require('bluebird');

function getInner(value){
    return  new Promise(function(resolve,reject){
        setTimeout(function(value){
            resolve(value);
        },1000,[value,"不明白","是啥"]);
    })
} 

function lastAync(value){
    return  new Promise(function(resolve,reject){
        setTimeout(function(value){
            resolve(value);
        },1000,value);
    })
} 

// console.log(getInner());b

function getPromise(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log("第一层");
            resolve("不搜");
            // resolve("pp");

        },1000);
    })
}

function lala(){
    return getPromise()
            .then(function(x){
                console.log(x)
                return getInner(x).then(function(thirdArray){
                    // console.log("ks");
                    var ksArray = thirdArray.map(function(value,index){
                        // console.log(value);
                        return lastAync(value);
                    })
                    return Promise.all(ksArray);
                });
            }).then(function(t){
                console.log(t);
            }).then(function(k){
                console.log("你好");
            })
}


function TurnAround(singger){
    this.singing = singger;
}

var t = [["1",["a","b","c","d"]],["2",["xx","yy","zz","dd"]]];


function test(){

    var tArray = t.map(function(value,index){
            var innerArray = value[1];
            var inPA = innerArray.map(function(value,index){
                return lala();
            })
            return Promise.all(inPA);
        })
    return Promise.all(tArray).finally(function(){
        console.log("中断");
    });
}


test();

这篇关于javascript - promise.all 嵌套无法保证内层的Promise执行顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆