我在使用node.js + express + mongodb做一个英语课堂测试系统, 其中有一个学生管理界面. 新增一个学生, 有以下字段: name(名称), age(年龄), grade(年级)等, 于是我封装了一个判断函数, 用于判断前端所传递的数据是否有误:
// 检查所传入的数据是否有效
function check_info(_id, name, age, grade) {
if ("" == name) {
return {status: false, msg: '名称不可为空'};
}
age = parseInt(age);
grade = parseInt(grade);
if (isNaN(age)) {
return {status: false, msg: '年龄必须为整数'};
}
if (isNaN(grade)) {
return {status: false, msg: '年级必须为整数'};
}
console.log("1");
if (_id) {
collection.find({_id: _id, name: name}).count(function (err, count) {
if (1 != count) {
return {status: false, msg: '编辑情况下, 名称不可更改!'};
}
});
} else {
console.log("2");
collection.find({name: name}).count(function (err, count) {
console.log("3");
if (0 != count) {
return {status: false, msg: '新增情况下, 数据库中已经存在此名称!'};
}
});
}
console.log("4");
return {status: true, msg: '正确'};
}
在这里, 很明显, 由于find数据库时候, 采用的是异步操作, 导致永远返回{status: true, msg: '正确'};
问题:
在实际项目中, 是如何解决这种情况的? 我查了数据库, 貌似还没有同步的解决方案出现?
我没有使用mongoose, 使用的是mongodb的本身api:
var express = require('express');
var router = express.Router();
var init = function (callback) {
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/test_system';
MongoClient.connect(url, function (err, db) {
var collection = db.collection('students');
callback(collection);
});
};
怪我咯2017-04-17 15:40:05
処理プロセスは確かに非同期です。ほとんどの言語/フレームワークでは、非同期処理が必要な場合は、非同期処理用にスレッドが開かれるため、非同期処理の数を制御するのが簡単です。ただし、Node の実装は少し異なります。JavaScript はシングルスレッド プログラムであるため、より時間のかかる操作は障害を避けるために非同期で処理されます。
コメント: シングルスレッドの非同期操作は説明するのが面倒です。私は、メインスレッドが UI を担当し、他のすべての処理は非同期で実行する必要があることを直接理解しています。他のスレッドでも。 Android はこの方向に開発を進めており、すでにネットワーク操作をメインスレッドで実行しないようにする必要があるため、このアプローチは理解できます。
非同期処理には、メッセージ通知、またはスレッド間の対話が含まれる必要があります。 Node では、コールバックを介して実装されます (シングルスレッドの非同期で複雑なため)。よりエレガントに言うと、オブザーバー パターンを介して実装されます。 ES5 の場合、コールバックを使用してコールバックを埋め込むのが最も簡単な方法です。もちろん、Node の使用がますます広くなるにつれて、この問題を解決するために多くのライブラリが登場し、これらを総称して Promise ライブラリと呼びます。明らかに ECMA もこの問題を認識しているため、Promise の実装は ES6/ES2015 に直接組み込まれています。
リーリー電話
リーリーPromise を使用する方がはるかに優れていますが、それでも書くのは比較的面倒です。特に、使用するライブラリが Promise でパッケージ化されていない場合、自分で変更するのは面倒です。
ES7 は、非同期呼び出しを同期するために async/await を実装する準備をしています (実際の同期ではなく、書き込み中の同期のみを指します)。また、KOA などの一部のライブラリは、ジェネレーターを介して非同期チェーンを実装しようとします。さらに詳しく知りたい場合は、KOA のドキュメントを参照してください。
PHP中文网2017-04-17 15:40:05
node.js に初めて触れたとき、この問題に慣れるのは難しいかもしれません。確かに、頭の中で組み立てラインのように実行されますが、デフォルトのメソッドは単なるコールバック関数です (これに関数を与えます)。ただし、コールバック関数は実行が完了するまで待機せずに他の処理を実行するため、クエリが実行されたときに結果を順番に取得することはできません。次の文は最後の文まで即座に実行されるため、結果は毎回同じになります。したがって、コールバック関数の次のステップを実行する必要がありますが、将来的には、あまりにも多くのステップが深くネストされていることがわかり、promise+generator と async+await について学習することになります。
戻る必要がある場合は、コールバック関数を受け入れ、この関数を呼び出してデータを転送できます。
あなたの例を視覚化してみましょう。
あなたのお父さんはあなたに醤油を買ってきて、それを買って鍋に入れるように頼みました。あなたの質問は、弟が帰ってきたら醤油を作るように頼むというプロセスです。ソースを作るとコールバック関数が実行され、このプロセスが頭の中にあるはずですが、あなたは兄に醤油を作ってもらい、鍋をお父さんに渡しました。もちろん、オイルポットは毎回空になります。
コンピューターがなければコードを書くことはできません。コードは最も直感的に理解できるものでなければなりません。