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 安装下依赖。