我有一个像这样的对象:
let myObject = {
'db1': [db1_file1Id,db1_file2Id,db_1file3Id],
'db2': [db2_file1Id, db2_file2Id]
...
}
我遍历这个对象和每次迭代:我连接到数据库,检索文件,做一些事情并保存文件。基本上是异步的东西。
for (let prop in myObject) {
if (myObject.hasOwnProperty(prop)) {
doStuff(prop, myObject[prop]);
}
}
现在doStuff函数确保我有一个本地范围,因此没有不一致。但是,由于每个循环内部的异步操作,执行不同步。我基本上需要一个db才能完全处理,然后继续下一个。我该如何解决这个问题?
我想到的一种方法是使用递归循环。但根据我的理解,这将要求我广泛地改变我的数据结构,这是次优的imo。
let arr; //containing my data
process(x) {
if (x < arr.length){
//process(x+1) is called inside doStuff after asynchronous operations are complete
doStuff(arr[x]);
}
}
答案 0 :(得分:2)
以下将按您的要求执行,它会返回一组解析值。
如果其中任何一个拒绝,你想停止处理吗?如果您需要进行一些更改,现在拒绝其中任何一个更改并拒绝继续处理它们在您的对象中的键(名为myObject
的对象):
var myObject = {
'one': ["one"],
'two': ["two"]
};
var doStuff = arr =>
console.log("starting:", arr[0]) ||
Promise.resolve(arr[0]);
var [promise,result] =
Object.keys(myObject)
.reduce(
([promise,results], key) =>
[
promise
.then(
resolve =>
doStuff(myObject[key])
)
.then(
resolve => results.push(resolve)&&resolve
)
.then(
resolve => console.log("done:", resolve)
)
,results
]
, [Promise.resolve(), []]
)
promise.then(
_ => {
console.log("done all",result)
}
);
&#13;
答案ayushgp使用递归,这是一个不需要做任何改变的工作示例:
var myObject = {
'one': ["one"],
'two': ["two"]
};
var doStuff = arr =>
console.log("starting:",arr[0]) ||
Promise.resolve(arr[0])
var process = (arr,processFn) => {
const rec = (arr,processFn,promise,results) =>
arr.length === 0
? promise.then(_=>results)
: promise
.then(_ => processFn(arr[0][1]))
.then(result=>results.push(result)&&console.log("resolved:",result))
.then(_ => rec(arr.slice(1),processFn,promise,results));
return rec(arr,processFn,Promise.resolve(),[]);
};
process(
Object.keys(myObject).map(key=>[key,myObject[key]]),
doStuff
)
.then(
results => console.log("done all, results:",results)
);
&#13;
答案 1 :(得分:1)
您可以使用{"value":["name","height","weight"],"done":false}
最后提出的解决方案。例如,
Object.entries(obj)
在doStuff里面:
let arrProps = Object.entries(myObject);
process(index) {
if (index < arrProps.length){
// Call the callback once you complete execution of doStuff
doStuff(arrProps[index], () => process(index + 1));
}
}
如果你想使用function doStuff(props, callback) {
// Process props
//finally in the promise of async call, on success call
.then(callback)
}
循环,你可以使用生成器函数。
答案 2 :(得分:1)
一种解决方案是让doStuff
返回Promise
,您可以使用then
调用来构建一连串的承诺。
Bluebird promise库通过.each
和.mapSeries
提供此功能。
您可以将其实现为:
Promise.forEachSeries = function(array, action) {
return array.reduce(function(prevPromise, value, index, array) {
return prevPromise.then(function() {
return action(value, index, array);
});
}, Promise.resolve());
}
您可以这样使用它:
Promise.forEachSeries(arr, doStuff);
答案 3 :(得分:1)
以下代码可能与您要求的内容相近。我使用索引i
和j
分别遍历数据库和文件:
var dbs = {
db1: ["q", "w", "e", "r"],
db2: ["t", "y"]
};
var names = Object.keys(dbs);
var db, x, i = 0, j = 0;
if (names.length > 0) {
db = dbs[names[i]];
x = db[j];
console.log("start");
asyncProcessing(x)
.then(onSuccess)
.catch(onFailure);
}
function onFailure (e) {
console.log("[FAILURE]", e);
console.log("end");
}
function onSuccess (xx) {
console.log("[SUCCESS]", xx);
j = (j + 1) % db.length; // next j
if (j === 0) i = i + 1; // next i
if (i < names.length) {
db = dbs[names[i]];
x = db[j];
asyncProcessing(x)
.then(onSuccess)
.catch(onFailure);
} else {
console.log("end");
}
}
function asyncProcessing (x) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
// force first two success then random
if (x === "q" || x === "w" || Math.random() * 3 > 1) {
resolve(x + x);
} else {
reject("Not lucky. Try again.");
}
}, 1000);
});
}
答案 4 :(得分:0)
Promise对象表示异步操作的最终完成(或失败)及其结果值。你可以试试。
addr = "......IP address is 2001:0000:3238:DFE1:63::FEFB. SUbnet mask is.........."
$("#myPara").delay(4500).fadeOut().promise().done(function(){
$("#myHeading").attr("style","display:none;") ;
for(var i=10;i<15;i++){
console.log(i);
}
});
console.log("Hello promise !");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="myPara"> Hello </p>
<h1 id="myHeading">to be hide</h1>