如何在嵌套函数调用中使用Promise

时间:2019-03-07 11:54:45

标签: javascript node.js promise

就像我以为我理解了承诺...我在下面的挣扎中评论了我的代码,但是从本质上讲,我只是不明白为什么当下面的代码运行时我得到以下结果

console.log("Finished Processing sheets")
console.log("Processing Errors")
console.log("sheet has completed processing")

当我期望的时候

console.log("sheet has completed processing")
console.log("Finished Processing sheets")
console.log("Processing Errors")

这是代码。

module.exports = async function(file) {
var sheets = await readXLSX(file, { getSheets: true })

  await Promise.each(Object.values(sheets), (sheet)=>{
    readXLSX(file, { sheet }).then((data)=>{
      //Process sheet data here
      return processSheet(data)
    })
  })
  console.log("Finished Processing sheets")
  console.log("Processing Errors")

}
var processSheet = async function(data){
//Do some processing and write excel data to database
await db.table('some_table')
.insert(.....)

return new Promise((resolve, reject)=>{
console.log("sheet has completed processing")
resolve()
})
}

2 个答案:

答案 0 :(得分:1)

我假设readXLSX返回了Promise,因为您在其上使用了.then()then返回Promise,因此,如果您希望Promise.each正常工作,则应执行return readXLSX(...).then(...);

这是一个简化了代码的示例:

//Promise.each emulation
Promise.each = function(arr, fn) {
  if(!Array.isArray(arr)) return Promise.reject(new Error("Non array passed to each"));
  if(arr.length === 0) return Promise.resolve(); 
  return arr.reduce(function(prev, cur) { 
    return prev.then(() => fn(cur))
  }, Promise.resolve());
};

//readXLSX emulation
var readXLSX = function(val){
    return new Promise(function(resolve, reject){
        setTimeout(function() {
            resolve(val);
        }, 1);
    });
};

var test = async function(file) {
  var sheets = { foo: 'bar', foo2: 'bar2' }

  await Promise.each(Object.values(sheets), (sheet)=>{
      return readXLSX(sheet).then((data)=>{
          //Process sheet data here
          return processSheet(data)
      });
  })
  console.log("Finished Processing sheets")
  console.log("Processing Errors")

};
var processSheet = async function(data){
  return new Promise((resolve, reject)=>{
    console.log("sheet has completed processing", data)
    resolve()
  })
};

test();

答案 1 :(得分:1)

您的问题是您的Promise.each回调没有return这个承诺,因此循环无法等待它。

Promise.each(Object.values(sheets), (sheet)=>{
  return readXLSX(file, { sheet }).then(processSheet)
//^^^^^^
})

或使用async / await

module.exports = async function(file) {
  const sheets = await readXLSX(file, { getSheets: true })

  await Promise.each(Object.values(sheets), async (sheet) => {
//                                          ^^^^^
    const data = await readXLSX(file, { sheet })
    return processSheet(data)
  })
  console.log("Finished Processing sheets")
  console.log("Processing Errors")
}

async function processSheet(data) {
  await db.table('some_table').insert(…)
  console.log("sheet has completed processing");
  return undefined; // no need to construct a promise here
}