簡體   English   中英

在 nodeJS 中的函數內調用函數

[英]Call a function inside a function in nodeJS

我正在使用 nodeJS 和 mongoDB。

我編寫了一個函數來獲取數據庫中最大的索引,以便在我在數據庫中發布新元素時能夠使用它。

我創建了一個函數來在我的數據庫中插入一個元素:

function postComparison(){

console.log("Titre : " + document.getElementById("Titre").value);

var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

var raw = JSON.stringify({
  "_id": getLastIndice()+1, // HERE
  "id_User": "2",
  "PseudoUser": "bob",
"Titre" :  document.getElementById("Titre").value
});

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: raw,
  redirect: 'follow'
};

fetch("http://localhost:3000/comparaison", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));}
</script>

我正在調用getLastIndice()函數來增加我在數據庫中的最后一個索引的索引。

函數getLastIndice()調用路由器:

function getLastIndice(){
    console.log("on appel la fonction get LastIndice");
      var requestOptions = {
      method: 'GET',
      redirect: 'follow'
      };

  fetch("http://localhost:3000/comparaison/getLastIndice", requestOptions)
  .then(response => response.text())
  //.then(result => document.getElementById("textRepBDD").innerHTML = result)
  .catch(error => console.log('error', error));
  console.log('appel de la fonction qui recupere le dernier indice avec comme réponse : ' + response );
  return parseInt(response);
}
</script>

在路由器內部我有:

comparaisonRouter.route('/getLastIndice')

.get( (req, res, next) => {
        var MongoClient = require('mongodb').MongoClient;
        var url = "mongodb://localhost:27017/";

        MongoClient.connect(url, function(err, db) {
        if (err) throw err;
        var dbo = db.db("siteComparaisonMax");
        //Sort the result by name:
        var sort = { _id: -1 }; // - 1 Pour trier dans un ordre decroissant.
        dbo.collection("comparaisons").find().sort(sort).limit(1).toArray(function(err, result) {
            if (err) throw err;
            //console.log(JSON.parse(result._id));
            console.log(result[0]._id);
            res.json(result[0]._id);
            db.close();
        });
        });

    })

函數 get last index 正在工作,但是當我調用postComparaison()函數時,它只是調用了getLastIndice() ,僅此postComparaison()

我想我在某個地方錯過了 next() 。

要從承諾中返回一個值,您可以使用.then() .then()方法不是用來記錄結果的。 postComparaison()可以調用以獲取結果:

function getLastIndice(){
    console.log("on appel la fonction get LastIndice");
    var requestOptions = {
        method: 'GET',
        redirect: 'follow'
    };

    // IMPORTANT! The `return` below in front of the `fetch()` is
    // what will return the value to the caller:
    return fetch("http://localhost:3000/comparaison/getLastIndice", requestOptions)
      .then(response => response.text())
      .then(result => {
          console.log('code INSIDE THIS THEN executes AFTER we get response : ' + result );
          return parseInt(result);
      })
      .catch(error => console.log('error', error));

      console.log('code OUTSIDE THE THEN ABOVE executes BEFORE we get response');
}

這是非常重要的。 函數底部的代碼執行FIRST 然后執行LAST 中的代碼。

為了澄清,讓我們從函數中刪除所有細節:

function getLastIndice() {
    // THIS HAPPENS FIRST
    console.log('first');        

    return fetch()
      .then(response => response.text())
      .then(result => {
          // THIS HAPPENS THIRD
          console.log('third');
          return parseInt(result);
      });

       // THIS HAPPENS SECOND
      console.log('second');
}

上面的代碼會記錄:

第一第二第三

但請注意:

function getLastIndice() {

    return fetch() // THIS RETURN IS IMPORTANT ! !

      .then(r => r.json())
      .then(r => parseInt(r));
}

所以基本上一個干凈版本的getLastIndice()可以簡單地寫成:

function getLastIndice() {

    var requestOptions = {
        method: 'GET',
        redirect: 'follow'
    };

    return fetch("http://localhost:3000/comparaison/getLastIndice", requestOptions)
      .then(x => x.text())
      .then(y => parseInt(y));

}

這就是所有需要的功能。 我們真的不需要(或不想)在這里捕獲錯誤,因為我們希望調用者能夠檢測到錯誤,因此我們只需刪除.catch()

現在該函數可以正常工作,下面是您在postComparison()使用它的postComparison()

function postComparison() {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    // Remember, .then() is how getLastIndice() RETURNS its value:
    getLastIndice().then(indice => {
    
        var raw = JSON.stringify({
            "_id": indice+1, // WE GOT THIS FROM .then of getLastIndice()
            "id_User": "2",
            "PseudoUser": "bob",
            "Titre" :  document.getElementById("Titre").value
        });

        var requestOptions = {
            method: 'POST',
            headers: myHeaders,
            body: raw,
            redirect: 'follow'
        };

        fetch("http://localhost:3000/comparaison", requestOptions)
            .then(response => response.text())
            .then(result => console.log(result))
            .catch(error => console.log('error', error));
   }
}

或者,您可以返回變量raw並在另一個.then()處理其余部分。 這就是 Promise 被發明的全部原因——通過鏈接.then()s來扁平化回調嵌套:

function postComparison() {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    // Remember, .then() is how getLastIndice() RETURNS its value:
    getLastIndice()
        .then(indice => {
            var raw = JSON.stringify({
                "_id": indice+1,
                "id_User": "2",
                "PseudoUser": "bob",
                "Titre" :  document.getElementById("Titre").value
            });

            return raw; // return this to the `then` below:
        })
        .then(requestBody =>
            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: requestBody, // requestBody comes from raw above
                redirect: 'follow'
            };

            return fetch("http://localhost:3000/comparaison", requestOptions);
        })
        .then(response => response.text())
        .then(result => console.log(result))
        .catch(error => console.log('error', error));

        // ^^ NOTE: all the then() are on the same level!
}

如果你想postComparison()返回的最終結果只是做我們一起做的同樣的事情getLastIndice()以上:添加return關鍵字前面getLastIndice()

function postComparison() {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    return getLastIndice() // THIS RETURN IS IMPORTANT !
        .then(indice => {
            var raw = JSON.stringify({
                "_id": indice+1,
                "id_User": "2",
                "PseudoUser": "bob",
                "Titre" :  document.getElementById("Titre").value
            });

            return raw;
        })
        .then(requestBody =>
            var requestOptions = {
                method: 'POST',
                headers: myHeaders,
                body: requestBody, // requestBody comes from raw above
                redirect: 'follow'
            };

            return fetch("http://localhost:3000/comparaison", requestOptions);
        })
        .then(response => response.text())
        .then(result => {
            console.log(result);
            return result; // return the result into the chain of then()
                           // this return is ALSO IMPORTANT
         })
        .catch(error => console.log('error', error));
}

一個類比:

使用 Promise 時,您必須始終記住then()中的代碼發生在函數結束之后,而不是之前! 如果你仔細想想,這實際上是有道理的。

例如,假設您要訂購比薩。 通常發生的事情是這樣的:

  1. 您致電Restaurant()並訂購比薩餅
  2. pizzaDeliveryGuy(() => will send you the pizza)
  3. 你放下電話
  4. 你等待pizzaDeliveryGuy()

注意,在上述事件pizzaDeliveryGuy().then()Restaurant()使得Prmoise送你一個比薩餅(使用pizzaDeliveryGuy() 盡管Restaurant()答應你提供比薩餅,然后才放下手機send you the pizza事件發生,你放下了電話。

您的困惑正是這樣:不了解未來會發生承諾。 即使餐廳在您放下電話之前向您承諾了披薩,披薩送貨員也會在您下訂單后將披薩發送給您。 類似地, Promise將在函數結束之后而不是之前執行.then()回調。

帶有異步/等待的現代代碼:

ECMAScript 版本 6 引入了兩個有助於簡化async代碼處理的關鍵字: asyncawait 它們建立在Promise之上,基本上是用於內聯Promise的特殊語法。

基本上,如果你寫這樣的東西:

async function x () {
    let y = await z();
    console.log(y);
}

Javascript 會將它編譯成這樣:

function x () {
    z().then(y => console.log(y));
}

使用async/await我們可以簡化您的代碼。 首先,我們可以像這樣重寫getLastIndice()

async function getLastIndice() {

    var requestOptions = {
        method: 'GET',
        redirect: 'follow'
    };

    let response = await fetch("http://localhost:3000/comparaison/getLastIndice", requestOptions);

    let txt = await response.text();

    return parseInt(txt);
}

因為我們使用await上面函數中的所有內容都是從上到下依次發生的:

async function getLastIndice() {
    // THIS HAPPENS FIRST
    var requestOptions = {
        method: 'GET',
        redirect: 'follow'
    };

    // THIS HAPPENS SECOND    
    let response = await fetch(URL, requestOptions);

    // THIS HAPPENS THIRD
    let txt = await response.text();

    // THIS HAPPENS LAST
    return parseInt(txt);
}

現在我們可以像這樣重寫postComparison()

async function postComparison() {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");

    try {

        let indice = await getLastIndice();

        var raw = JSON.stringify({
            "_id": indice+1,
            "id_User": "2",
            "PseudoUser": "bob",
            "Titre" :  document.getElementById("Titre").value
        });

        var requestOptions = {
            method: 'POST',
            headers: myHeaders,
            body: raw
            redirect: 'follow'
        };

        let response = await fetch("http://localhost:3000/comparaison", requestOptions);

        let result = await response.text())

        console.log(result);
        return result;
    }
    catch(error) {
        console.log('error', error);
    }
}

如您所見,對於像這樣的簡單順序代碼, async/await更容易閱讀。 只是不要忘記await結果。

盡管如此,即使您使用async/await我認為了解 Promises 的工作方式以及.then()工作方式至關重要,因為async/await是建立在.then()之上的。 在某些情況下,您希望兩個或多個事物並行運行而不是順序運行,這就是您需要回到承諾和回調的時候。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM