как использовать обещания в вызовах вложенных функций - PullRequest
1 голос
/ 07 марта 2019

Так же, как я думал, что понял обещания ... Я прокомментировал мой код ниже, где я борюсь, но по сути, я просто не могу понять, почему, когда код ниже запущен, я получаю следующий результат

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 ]

1 голос
/ 07 марта 2019

Ваша проблема в том, что ваш 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
}
1 голос
/ 07 марта 2019

Я предположил, 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...