2017-03-13 78 views
0

我有一個使用異步瀑布的問題,我發現在調用第二個回調(cbNumPages)之後,第一個參數「pages」是下一個函數的實際回調,而不是最後一個參數「cbGetFiles」它應該是(據我所知異步瀑布說,最後一個參數應該總是回調,在這種情況下,顯然不是)。NodeJs異步瀑布(回調方法不是函數)

的代碼如下:

async.waterfall 
      ([ 
       function(cbNumPages) 
       { 
        request({ 
         url: 'any-url', 
         qs: {}, 
         method: 'GET', 
         headers: { 
          'Authorization' : 'any-auth' 
         } 
        }, (err, response, body) => { 
         if (!err && response.statusCode == 200) 
         { 
          var $ = cheerio.load(body); 
          var pagesList = $('ol.aui-nav').children(); 
          if(pagesList.length<1) 
          { 
           var numPages = 1; 
          } else { 
           var numPages = pagesList.length-2; 
          } 
          console.log(numPages); 
          var pages = new Array(numPages), 
           total = numPages*20, 
           iterator = 0; 

          async.eachSeries(pages, function(page, cb) 
          { 
           if(page>1) 
           { 
            pages[iterator] = iterator; 
           }else { 
            pages[iterator] = iterator*20; 
           } 
           iterator++; 
           cb(); 
          }, function(err){ 
           if(err) cbNumPages(err); 
           cbNumPages(null, pages); 
          }); 
         } else { 
          cbNumPages(err); 
         } 
        }) 
       }, 

       function(pages, cbGetFiles) 
       { 
        var files = []; 
        var limitDate = moment().tz('Europe/Madrid').subtract(330,'days').format(); 

        async.eachSeries(pages, function(page, cb) 
        { 
         request({ 
          url: 'any-url'+page, 
          qs: {}, 
          method: 'GET', 
          headers: { 
           'Authorization' : 'any-auth' 
          } 
         }, (err, response, body) => { 
          if(!err && response.statusCode == 200) 
          { 
           var $ = cheerio.load(body); 
           var rows = $('tr[id^=\'attachment-\']'); 
           async.eachLimit(rows, 1, function(row, cb) 
           { 
            var id = row.attribs['id']; 
            var file = row.attribs['data-attachment-filename']; 
            var author = $(row).children('.creator').text().trim(); 
            var created = $(row).children('.created-date').text().trim(); 
             created = moment.tz(created, 'MMM D, YYYY', 'Europe/Madrid').format(); 
            var urlFile = 'simple-file' + $(row).children('.filename-column').children('.filename').attr('href'); 
            var extension = row.attribs['data-attachment-filename'].split('.'); 
             extension = extension[extension.length-1]; 
            if(created<limitDate && validExtensions.indexOf(extension)>-1) 
            { 
             var f = '{ "id": "' + id + '",'; 
              f += ' "file": "' + file + '",'; 
              f += ' "url": "' + urlFile + '",'; 
              f += ' "author": "' + author + '",'; 
              f += ' "modified": "' + created + '" }'; 
             files.push(JSON.parse(f)); 
            } 
            cb(); 
           }, (err) => { 
            if(err) cbGetFiles(err); 
           }); 
           cb(); 
          } else { 
           cb(err); 
          } 
         }); 
        }, function(err){ 
         if(err){ 
          cbGetFiles(err); 
         } else { 
          cbGetFiles(null, files); 
         } 
        }); 
       }, 

       function(files, cbGetAutors) 
       { 
        var filesFinal = {}; 
        for(var f in files) 
        { 
         if(!filesFinal[files[f].author]) 
         { 
          var ff = {}; 
          for(var i in files) 
          { 
           if(files[i].author === files[f].author) 
           { 
            ff[files[i].file] = files[i].url; 
           } 
          } 
          filesFinal[files[f].author] = ff; 
         } 
        } 
        cbGetAutors(null, JSON.parse(JSON.stringify(filesFinal))); 
       }, 

       function(filesFinal, cbSendEmail) 
       { 
        var authors = Object.keys(filesFinal); 
        async.eachSeries(authors, function(author, cb) 
        { 
         var name = author.split(' '); 

         var email = '[email protected]'; 
         var msg = '<p>Hi ' + author + ',</p><p>how is it going:</p><p>'; 
         for(var a in Object.keys(filesFinal[author])) 
         { 
          msg += '<p style="margin-left:20px"> '+ICON_DOC+' <a href="'; 
          msg += filesFinal[author][Object.keys(filesFinal[author])[a]]+'">'+Object.keys(filesFinal[author])[a]+'</a></p>'; 
         } 
         msg += '</p></p><p><b>NOTE: This is a no-reply address.</b></p><p>Have a nice day! '+ICON_MONKEY+'</p>'; 

         var message = { 
          text: msg, 
          from: '[email protected]', 
          to:  email, 
          bcc:  '', 
          subject: 'Sample subject', 
          attachment: [{data: msg, alternative: true}] 
         }; 

         serverEmail.send(message, function(err, message) 
         { 
          if(err) 
          { 
           cb(err); 
          } else { 
           console.log(message); 
           cb(); 
          } 
         }); 

        }, function(err){ 
         if(err) cbSendEmail(err); 
         cbSendEmail(); 
        }); 
       } 

      ], (err) => { 
       if(err) console.log(err); 
      }); 

我想知道是否有控制這個問題還是有辦法,至少,如果有什麼我想要做的另一種選擇。

感謝。

+1

在你的代碼'如果(ERR)cbNumPages(ERR);'用'return' 。檢查http://caolan.github.io/async/ – Sangharsh

+1

中的「常見陷阱」部分@Sangharsh會不會導致「回調已被調用」錯誤,如果這是問題所在? @avilac是否有可能來自'any-url'的返回代碼不是200,因此導致調用'cbNumPages(err)''err'等於'null'?這將使'async'認爲沒有提供任何錯誤和返回值,導致回調作爲第一個參數傳遞給'瀑布'的第二個函數。 – YSK

+0

@YSK你的猜測很可能是正確的。我的評論是關於編碼實踐。 – Sangharsh

回答

2

使用異步瀑布的更好(整潔)的方式。

確保在任何回調函數之前使用return。我已經在代碼中添加了它們。另外,如果要嵌套每個系列,最好給回調函數指定一個不同於父回調函數的名稱。

我已經改變了 'CB' 孩子async.series以 'inner_cb'

更新的代碼:

async.waterfall 
([ 
    funcOne, 
    funcTwo, 
    funcThree, 
    funcFour  
], (err) => { 
    if(err) console.log(err); 
}); 

funciton funcOne(cbNumPages) { 
    request({ 
     url: 'any-url', 
     qs: {}, 
     method: 'GET', 
     headers: { 
      'Authorization' : 'any-auth' 
     } 
    }, (err, response, body) => { 
     if (!err && response.statusCode == 200) 
     { 
      var $ = cheerio.load(body); 
      var pagesList = $('ol.aui-nav').children(); 
      if(pagesList.length<1) 
      { 
       var numPages = 1; 
      } else { 
       var numPages = pagesList.length-2; 
      } 
      console.log(numPages); 
      var pages = new Array(numPages), 
       total = numPages*20, 
       iterator = 0; 

      async.eachSeries(pages, function(page, cb) 
      { 
       if(page>1) 
       { 
        pages[iterator] = iterator; 
       }else { 
        pages[iterator] = iterator*20; 
       } 
       iterator++; 
       return cb(); 
      }, function(err){ 
       if(err) return cbNumPages(err); 
       return cbNumPages(null, pages); 
      }); 
     } else { 
      return cbNumPages(err); 
     } 
    }) 
} 

function funcTwo(pages, cbGetFiles) { 
    var files = []; 
    var limitDate = moment().tz('Europe/Madrid').subtract(330,'days').format(); 

    async.eachSeries(pages, function(page, cb) 
    { 
     request({ 
      url: 'any-url'+page, 
      qs: {}, 
      method: 'GET', 
      headers: { 
       'Authorization' : 'any-auth' 
      } 
     }, (err, response, body) => { 
      if(!err && response.statusCode == 200) 
      { 
       var $ = cheerio.load(body); 
       var rows = $('tr[id^=\'attachment-\']'); 
       async.eachLimit(rows, 1, function(row, inner_cb) 
       { 
        var id = row.attribs['id']; 
        var file = row.attribs['data-attachment-filename']; 
        var author = $(row).children('.creator').text().trim(); 
        var created = $(row).children('.created-date').text().trim(); 
         created = moment.tz(created, 'MMM D, YYYY', 'Europe/Madrid').format(); 
        var urlFile = 'simple-file' + $(row).children('.filename-column').children('.filename').attr('href'); 
        var extension = row.attribs['data-attachment-filename'].split('.'); 
         extension = extension[extension.length-1]; 
        if(created<limitDate && validExtensions.indexOf(extension)>-1) 
        { 
         var f = '{ "id": "' + id + '",'; 
          f += ' "file": "' + file + '",'; 
          f += ' "url": "' + urlFile + '",'; 
          f += ' "author": "' + author + '",'; 
          f += ' "modified": "' + created + '" }'; 
         files.push(JSON.parse(f)); 
        } 
        return inner_cb(); 
       }, (err) => { 
        if(err) return cbGetFiles(err); 
       }); 
       return cb(); 
      } else { 
       return cb(err); 
      } 
     }); 
    }, function(err){ 
     if(err){ 
      return cbGetFiles(err); 
     } else { 
      return cbGetFiles(null, files); 
     } 
    }); 
} 

function funcThree(files, cbGetAutors) { 
    var filesFinal = {}; 
    for(var f in files) 
    { 
     if(!filesFinal[files[f].author]) 
     { 
      var ff = {}; 
      for(var i in files) 
      { 
       if(files[i].author === files[f].author) 
       { 
        ff[files[i].file] = files[i].url; 
       } 
      } 
      filesFinal[files[f].author] = ff; 
     } 
    } 
    return cbGetAutors(null, JSON.parse(JSON.stringify(filesFinal))); 
} 

function funcFour(filesFinal, cbSendEmail) { 
    var authors = Object.keys(filesFinal); 
    async.eachSeries(authors, function(author, cb) 
    { 
     var name = author.split(' '); 

     var email = '[email protected]'; 
     var msg = '<p>Hi ' + author + ',</p><p>how is it going:</p><p>'; 
     for(var a in Object.keys(filesFinal[author])) 
     { 
      msg += '<p style="margin-left:20px"> '+ICON_DOC+' <a href="'; 
      msg += filesFinal[author][Object.keys(filesFinal[author])[a]]+'">'+Object.keys(filesFinal[author])[a]+'</a></p>'; 
     } 
     msg += '</p></p><p><b>NOTE: This is a no-reply address.</b></p><p>Have a nice day! '+ICON_MONKEY+'</p>'; 

     var message = { 
      text: msg, 
      from: '[email protected]', 
      to:  email, 
      bcc:  '', 
      subject: 'Sample subject', 
      attachment: [{data: msg, alternative: true}] 
     }; 

     serverEmail.send(message, function(err, message) 
     { 
      if(err) 
      { 
       return cb(err); 
      } else { 
       console.log(message); 
       return cb(); 
      } 
     }); 

    }, function(err){ 
     if(err) return cbSendEmail(err); 
     return cbSendEmail(); 
    }); 
} 
+1

感謝您的時間,一個好的建議總是有幫助的! :) – avilac

+0

總是樂於幫助:) –

0

正如@YSK在評論中所說的,我從response.statusCode獲得了401,因此它被誤導爲cbSendEmail(err),其錯誤爲beying null。在瀑布的第一個參數中做下一個方法,而不是第二個參數。