2017-09-29 29 views
14

次のスニペットでは、最初の非同期メソッドのフィールドを検証したいと思います。Node.js、Async、Formidableによるエラー処理

有効でない場合は、すぐにユーザーにエラーを返信したいと思います。

どうすればよいですか?

var form = new formidable.IncomingForm(); 

async1.series([ 
    function (callback) { 
     form.parse(req); 

     form.on('field', function (name, val) { 
      // Get the fields 
     }); 

     form.on('fileBegin', function (name, file) { 
      if (file.name !== "") { 
       file.path = __dirname + '/upload/' + file.name; 
      } 
     }); 
     callback(); 
    }, 
    function (callback) { 
     form.on('file', function (name, file) { 
      try { 
       // Do something with the file using the fields retrieved from first async method 
      } 
      catch (err) { 
       logger.info(err); 
      } 
     }); 


     callback(); 
    } 
], function (err) { 
    //the upload failed, there is nothing we can do, send a 500 

    if (err === "uploadFailed") { 
     return res.send(500); 
    } 

    if (err) { 
     throw err; 
    } 
    return res.status(200); 

}); 
+0

'復帰コールバック(ERR)'すぐにあなたがフィールドをチェックしているかのブロックから、そのコールバックが直接あなたが '送っているあなたの'コールバックハンドラのfunction'を実行しますレスポンスコード。 – Zeeshan

答えて

1

私はフィールドが入って来ているとき、これがあるので、これは検証するには良い場所であることを仮定している:

form.on('field', function (name, val) { 
    //if values are null 
    if (!name || !val) { 
     //pass the callback an error 
     return callback("Values are null") 
    } 
    // Get the fields 
}); 

このことができます場合は私に知らせてください。

+0

これらのエラーはどこにスローされますか? API呼び出しにエラーを返す方法はありますか? –

+0

私のコードでは、エラーパラメータを介して非同期シリーズの最後の関数に送られると思います。それをAPI呼び出しに送るには(私はExpressのようなものを想定しています)、おそらくあなたは 'resを返すことができます。send( 'Values are null') –

3

var form = new formidable.IncomingForm(); 
 

 
async1.series([ 
 
    function (callback) { 
 
     form.parse(req); 
 

 
     form.on('field', function (name, val) { 
 
      if (!name || !val) { 
 
       // the moment callback is called with an error, async will stop execution of any of the steps 
 
       // in the series and execute the function provided as the last argument 
 
       // idimoatic node, when calling the callback with instance of Error 
 
       return callback(new Error('InvalidParams')); 
 
      } 
 

 
      /** 
 
      * This is from async documentation: https://caolan.github.io/async/docs.html#series 
 
      * Run the functions in the tasks collection in series, each one running once the previous function 
 
      * has completed. If any functions in the series pass an error to its callback, no more functions are 
 
      * run, and callback is immediately called with the value of the error. Otherwise, callback receives 
 
      * an array of results when tasks have completed. 
 
      */ 
 
     }); 
 

 
     form.on('fileBegin', function (name, file) { 
 
      if (file.name !== "") { 
 
       file.path = __dirname + '/upload/' + file.name; 
 
      } 
 
     }); 
 

 
     form.on('end', function() { 
 
      // call callback with null to specify there's no error 
 
      // if there are some results, call it like callback(null, results); 
 
      return callback(null); 
 
     }); 
 

 
     // if you call the callback immediately after registering event handlers for on('field') etc, 
 
     // there will be no time for those events to be triggered, by that time, this function will be 
 
     // done executing. 
 
     //callback(); 
 
    }, 
 
    function (callback) { 
 
     form.on('file', function (name, file) { 
 
      try { 
 
       // Do something with the file using the fields retrieved from first async method 
 
      } 
 
      catch (err) { 
 
       logger.info(err); 
 
       return callback(err); 
 
      } 
 
     }); 
 

 
     // This should also not be called immediately 
 
     //callback(); 
 
    } 
 
], function (err) { 
 
    //the upload failed, there is nothing we can do, send a 500 
 

 
    if (err === "uploadFailed") { 
 
     return res.send(500); 
 
    } 
 

 
    if (err.message === 'InvalidParams') { 
 
     // This will be immediately returned to the user. 
 
     return res.sendStatus(400); 
 
    } 
 

 
    if (err) { 
 
     // I'm not sure if this was just for the example, but if not, you should not be throwing an error 
 
     // at run time. 
 
     throw err; 
 
    } 
 
    return res.status(200); 
 

 
});

私は私がどこで、どのようにエラーを作成する方法と、それをすぐにユーザーにまで吹き込んだために表示するために必要なコードにいくつかのコメントを追加しました。

参照:Async Documentation

P.S.コードスニペットは実行可能ではありませんが、コードをよりよく表現しています。

- 編集 - 別のスニペットを追加して、コメントからより多くを知った後

。あなたは不当にコールバックとイベントの処理を混同しています。 form.parseにコールバックを渡すだけで、すべてのフィールドが収集されるとコールバックが呼び出されます。あなたは、検証を行うことができますすぐにエラーを返すか、ただフォームフィールドをすぐに処理します。

form.parse(req, function(err, fields, files) { 
    if (err) return res.sendStatus(400); 
    if (fields.areNotValid()) return res.sendStatus(400); 
    // parse fields 
}); 

または、イベントハンドラを登録できます。すべてのイベントは、async.seriesのように同時に処理されます。

var form = new formidable.IncomingForm(); 
 

 
form.parse(req); 
 
form.on('field', (name, val) => { 
 
    if (!name || val) { 
 
    console.log('InvalidParams') 
 
    return res.sendStatus(400); 
 
    } 
 
}); 
 
form.on('fileBegin', (name, file) => { 
 
    if (file.name !== "") { 
 
    file.path = __dirname + '/upload/' + file.name; 
 
    } 
 
}); 
 
form.on('file', (name, file) => { 
 

 
}); 
 
form.on('error', (err) => { 
 
    console.log('ParsingError'); 
 
    return res.sendStatus(400); 
 
}) 
 
form.on('end',() => { 
 
    if (res.headersSent) { 
 
    console.log('Response sent already') 
 
    } else { 
 
    // handle what you want to handle at the end of the form when all task in series are finished 
 
    return res.sendStatus(200); 
 
    } 
 
});

+0

これは、エラーを返すときにコールバック()がすでにエラーと呼ばれる原因になります。 form.on( 'end')のコールバックでエラーが発生しました –

+0

@Robben_Ford_Fan_boy Gotcha!私は問題をよりよく理解し、私の答えを更新しました。編集内容を確認し、それが役立つかどうかお知らせください。 –

5

私は機能にチェックインフォームを抽出します:

var form = new formidable.IncomingForm(); 

function check(name, cb, err){ 
return new Promise((res,rej)=>{ 
    form.on('field', function (n, val) { 
     if(n !== name) return; 
     if(cb(val)){ 
      res(val); 
     }else{ 
      rej(err); 
     } 
    }); 
}); 
} 

form.parse(req); 

だから今我々がチェックを実装し、それらを要約するPromise.allを使用することができます。

Promise.all(
    check("username", val => val.length > 4,"username isnt valid"), 
    check("password", val => true,"we need a password") 
).then(_=>res.json({status:200})) 
    .catch(err => res.json({err})); 

すべてのパラメータがすべて渡されていない場合、これは無限に。終了した場合は終了します。

const ended = new Promise((_,rej)=>form.on("end",()=>rej("params required")); 

Promise.race(
ended, 
    Promise.all(
    check("username", val => val.length > 4,"username isnt valid"), 
    check("password", val => true,"we need a password") 
) 
).then(_=>res.json({status:200})) 
.catch(err => res.json({err})); 

これで、データフローが良好になりました。例えば:

あなたがエラーでコールバックを返すことができます
const login = Promise.all(
    //usable as one liners 
check("username", val => val.length >= 8,"username invalid"), 
//or more extensible 
check("password", val =>{ 
    if(val.length < 8) return false; 
    //other checks 
    console.log(password); 
    return true; 
},"password invalid") 
//the field values are resolved by the promises so we can summarize them below 
).then(([username,password])=> 
    //a random (maybe async) call to evaluate the credentials 
    checkAgainstDB(username,password) 
    //we can directly fail here, err is "password invalid" or "username invalid" 
).catch(err =>res.json({error:"login failed",details:err})); 

//another parameter can be extra handled  
const data = check("something",val => val.length); 

//we need to summarize all the possible paths (login /data in this case) to one that generates the result 
Promise.race(
//here we join them together 
Promise.all(login,data) 
    .then((l,d)=>res.json(whatever), 
//and we use the ended promise (from above) to end the whole thing 
ended 
    //and at last the errors that can occur if the response ended or that have not been canceled early 
).catch(e => res.json(e)); 
関連する問題