JavaScript中的嵌套异步回调

时间:2018-05-14 21:38:59

标签: javascript mysql node.js asynchronous

我试图准确了解JavaScript中的异步如何工作。 在下面的示例中,我在另一个异步数据库调用的回调中进行嵌套数据库查找(在示例中我只是使用setTimeout

我试图跟踪我完成所有产品(包括嵌套数据库调用)的时间的方法是递增一个名为index的变量并检查{{1} }。

这个数据库库不支持开箱即用的Promise,所以我真的不确定还能做什么。这似乎不是正确的做法。

index == fake_data.length

我觉得我错过了一些非常基本的东西......

2 个答案:

答案 0 :(得分:1)

您可以将回调样式代码转换为基于承诺。看看http://bluebirdjs.com/docs/api/promise.promisify.html

或者您可以使用此代码段https://gist.github.com/joelnet/ece690e942223954b1b7997ba3b1cb00#file-promisify-js

function promisify(func) {
  return (...args) =>
    new Promise((resolve, reject) => {
      const callback = (err, data) => err ? reject(err) : resolve(data)

      func.apply(this, [...args, callback])
  })
}

答案 1 :(得分:1)

我不确定你的问题是什么,但看起来好像你正在尝试使用setTimeout来模拟数据库调用,并希望只是承诺。如果这是正确的,我建议创建单独的函数作为您的数据库层,以便它们可以与真实的东西交换。如果你想使用setTimeout,那么也将它包装在一个承诺中。类似的东西:

const fake_data = [{ type: 4 }, { type: 4 }, { type: 1 }, { type: 1 }, { type: 4 }, { type: 3 }, { type: 2 }];

// this just wraps setTimeout in a promise
const simulateWork = (time, func) => {
  return new Promise(resolve => {
    setTimeout(() => resolve(func()), time)
  })
}

const getProducts = () => simulateWork(1200, () => fake_data)
const handleProduct = product => simulateWork(400, () => {
  // do something with a product after some time
})

// the you can call things like
getProducts.then(products => {
  products.forEach(handleProduct)
})

更新

所以,看起来你想要做一堆异步事情,然后一旦完成就做一些事情。一个很好的候选者是Promise.all(),你传递一系列异步承诺工作,直到所有任务都解决后才能完成。

使用上面的帮助函数,您可以执行以下操作:

// function to get unique objects
const getUnique = (arr, getVal) => {
  var hash = {}
  var output = []
  arr.forEach(item => {
    if(!hash[getVal(item)]){
      hash[getVal(item)] = true
      output.push(item)
    }
  }
  return output
}

getProducts.then(products => {
  // get a list of unique products and map to new work
  Promise.all(getUnique(products, p => p.type).map(product => handleProduct))
    // this will be called once all data completed
    .then(() => test2())
}