2017-06-28 1 views
0

Webサイトを処理するために使用するNode.jsサーバーがあります。私は、データベースと対話するためのAPIを作ろうとしています。 Knex.jsを使用してデータベースを管理する必要があります。Knex.jsを使用してDBを照会する関数は未定義を返します

Knexの初期化とデータベースとその単一テーブルの作成(現在のところ)はうまくいきます。私がここでやろうとしているのは、引数としてidを指定すると、対応する行を検索して返す関数です。ここで

私はテーブルを作成します。

// create tables in the database 
function createDoctorsTable() { 
    jcdb.schema.hasTable("doctors").then(function (exists) { 
     if (!exists) { 
      jcdb.schema.createTable("doctors", function (table) { 
       table.integer("id"); 
       table.string("name").notNullable(); 
       table.string("surname").notNullable(); 
       table.string("presentation"); 
       table.string("professional_story"); 
       table.string("photo"); 
       table.string("mail"); 
       table.string("phone"); 
      }).then(function() { 
       return Promise.all(
        _.map(doctorsDBfile, function (v) { 
         return jcdb("doctors").insert(v); 
        }) 
       ); 
      }); 
     } 
     else { 
      return true; 
     } 
    }); 
} 

そして、これは私がやろうとしている機能です。

function getDoctorById(id) { 
    var result; 
    jcdb("doctors").where("id", id) 
     .then(function(query) { 
     result = JSON.stringify(query); 
     }); 
    return result; 
} 

その後、私は、私は必要なすべてを呼び出す:

app.set("port", serverPort); 

init_jcdb(); 
createDoctorsTable(); 

/* Start the server on port 3000 */ 
app.listen(serverPort, function() { 
    console.log(`Your app is ready at port ${serverPort}`); 
    console.log(getDoctorById(2)); 
}); 

getDoctorByIdへの呼び出しは()undefinedを返します!私が関数内にconsole.log()を置くと、行が正しく出力されます。 私は何が間違っていますか?

PS:私はjsのトータルnoobです。ちょうど昨日私は初めてそれを見ました。

答えて

2
function getDoctorById(id) { 
    var result; 
    jcdb("doctors").where("id", id) 
     .then(function(query) { 
     result = JSON.stringify(query); 
     }); 
    return result; 
} 

代わりにしてみてください:

function getDoctorById(id) { 
    return jcdb("doctors").where("id", id) 
     .then(function(query) { 
      var result = JSON.stringify(query); 
      return result; 
     }); 
} 

約束は、あなたがより簡単に非同期コードを使用してみましょう。 thenを使用している場合は、コールバック関数を実際に呼び出すことになり、チェーン内の前回の約束の結果がコールバック関数のパラメータとして呼び出されます。

しかし、そうするためには、あなたはコールバックのパラメータに行くつもりされている値である、約束のコールバック(あなたがthenに渡す機能)の中から値を返す必要があり、

とpromise-returning-function自体(この場合はjcdb)も返します。約束しているのはthenです。同じロジックに続い

、 あなたが好きではないconsole.log()機能はここで行うことができます覚えて、ので

console.log(getDoctorById(2)); 

は、関数がpromise、ない値を返します。コールバック関数のパラメータとして値/ sを間接的に返します。これは私たちを与える:

getDoctorById(2).then(function(result) { 
    console.log("result:", result); 
}) 

最後に一つ、 あなたの最初の関数、createDoctorsTable()は、非同期です。場合によってはgetDoctorById()の前に実行されることがあります。

だから、最初、私たちはgetDoctorByIdは、厳密にそれの後に実行させることができるようにのは、あなたのcreateDoctorsTable()から約束を返してみましょう:

function createDoctorsTable() { 
    return jcdb.schema.hasTable("doctors").then(function (exists) { 
    ....... 

(注意:私はreturn文を追加して、残りはよさそうです)。(init_jcdb()は約束を返すと仮定して)このようなあなたの最終的なコードを見て何かを作るために、その後

とあなたのapp.listenを変更、:

// create tables in the database 
function createDoctorsTable() { 
    return jcdb.schema.hasTable("doctors").then(function (exists) { 
     if (!exists) { 
      jcdb.schema.createTable("doctors", function (table) { 
       table.integer("id"); 
       table.string("name").notNullable(); 
       table.string("surname").notNullable(); 
       table.string("presentation"); 
       table.string("professional_story"); 
       table.string("photo"); 
       table.string("mail"); 
       table.string("phone"); 
      }).then(function() { 
       return Promise.all(
        _.map(doctorsDBfile, function (v) { 
         return jcdb("doctors").insert(v); 
        }) 
       ); 
      }); 
     } 
     else { 
      return true; 
     } 
    }); 
} 

function getDoctorById(id) { 
    return jcdb("doctors").where("id", id) 
     .then(function(query) { 
      var result = JSON.stringify(query); 
      return result; 
     }); 
} 


app.set("port", serverPort); 

    init_jcdb() 
     .then(function() { 
      return createDoctorsTable(); 
     }) 
     .then(function() { 
      getDoctorById(2).then(function(result) { 
       console.log("result:", result); 
      }) 
     }) 
     .then(function() { 
      /* Start the server on port 3000 */ 
      app.listen(serverPort, function() { 
       console.log(`Your app is ready at port ${serverPort}`); 
      } 
     }); 
}); 

このコードを書くためのバリエーションの豊富があります。

JavaScriptの非同期モデル、およびJavaScriptの約束について詳しくお読みください。

+0

関数で直接値を返すことはできませんか?たとえば、特定のIDのデータベースに値が必要なhttpページなど、この関数をどのように使用しますか?私は値を返すことは管理が簡単だと考えました。 createDoctorsTable()のために、非同期について考えて、それ以降の呼び出しとして作成しようとしましたが、あまり成功しませんでした。 とにかくありがとうございました:) –

+0

これはできません:)これは期日ですJavaScriptの非同期性JSは、関数呼び出しのような同期コードを実行するスレッドを1つだけ使用します。 jcdb関数の背後にあるコードなどの非同期コードは、JSエンジン実装へのバインディングを使用します.JSエンジン実装は、メインスレッドと並行して実行されますが、透過的に実行されます。他のスレッドにはアクセスできず、彼らは存在しません。 これは、コードが書かれたのと同じ順序で実行されるとは限らないためです。 – nadavvadan

関連する問題