同步迭代javascript对象 [英] Iterating javascript object synchronously

查看:100
本文介绍了同步迭代javascript对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的对象:

I have an object like so:

let myObject = {
'db1': [db1_file1Id,db1_file2Id,db_1file3Id],
'db2': [db2_file1Id, db2_file2Id]
...
}

我遍历此对象并在每次迭代中进行遍历:我连接到数据库,检索文件,执行一些操作并将文件保存回去.基本上是异步的东西.

I iterate through through this object and on each iteration: I connect to the database, retrieve the file, do some stuff and save the file back. Basically asynchronous stuff.

  for (let prop in myObject) {
    if (myObject.hasOwnProperty(prop)) {
      doStuff(prop, myObject[prop]);
    }
  }

现在,doStuff函数可确保我具有本地范围,因此不会出现任何不一致之处.但是,由于每个循环中的异步操作,执行仍是不同步的.我基本上需要先完成一个数据库的处理,然后再进行下一个数据库的处理.我该如何解决?

Now the doStuff function makes sure I have a local scope so there is no inconsistencies. But still, the execution is not synchronous due to the asynchronous operations inside each loop. I basically need one db to be completely processed before moving on to the next. How do I fix this?

我想到的一种方法是具有递归循环.但是根据我的理解,这将要求我广泛更改数据结构,这是次优的imo.

One approach that I thought of was to have recursive loop. But as per my understanding, this would require me to change my data structure extensively which is sub-optimal 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]);
 }
}

推荐答案

以下内容将按照您的要求进行操作,它返回一组解析值.

The following will do what you ask, it returns an array of resolve values.

如果其中任何一个拒绝,您是否要停止处理?如果您需要进行一些更改,现在它会拒绝是否有任何拒绝并且不会继续处理它们在您的对象(名为myObject的对象)中的键:

Do you want to stop processing if any one of them rejects? In case you need to make some changes, now it rejects if any of them reject and won't continue processing they keys in your object (object named 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)
  }
);

ayushgp的答案使用递归,这是一个有效的示例,不需要对doSomething进行更改:

The answer ayushgp uses recursion, here is a working example that doesn't need changes to doSomething:

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)
);

这篇关于同步迭代javascript对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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