web-dev-qa-db-fra.com

Comment puis-je attendre qu'une promesse se termine avant de renvoyer la variable d'une fonction?

Je me bats toujours avec les promesses, mais je fais des progrès grâce à la communauté d’ici.

J'ai une simple fonction JS qui interroge une base de données Parse. Elle est supposée renvoyer le tableau de résultats, mais à cause de la nature asynchrone de la requête (d'où les promesses), la fonction retourne avant les résultats, me laissant avec un tableau non défini.

Que dois-je faire pour que cette fonction attende le résultat de la promesse?

Voici mon code:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    var promise = query.find({
               success: function(results) {
               // results is an array of Parse.Object.
                             console.log(results);
                             //resultsArray = results;
                             return results;
               },

               error: function(error) {
               // error is an instance of Parse.Error.
                             console.log("Error");
               }
    });                           

}
120
mac_55

Au lieu de renvoyer resultsArray, vous renvoyez une promesse pour un tableau de résultats, puis then sur le site d’appel. Cela présente l’avantage supplémentaire de l’appelant de savoir que la fonction effectue des E/S asynchrones. La concurrence de codage en JavaScript est basée sur cela - vous voudrez peut-être lire cette question pour avoir une idée plus large:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    return query.find({});                           

}

// later
resultsByName("Some Name").then(function(results){
    // access results here by chaining to the returned promise
});

Vous pouvez voir plus d'exemples d'utilisation de promesses d'analyse avec des requêtes dans le blog de Parse à ce sujet .

56
Benjamin Gruenbaum

Que dois-je faire pour que cette fonction attende le résultat de la promesse?

Utilisez async/await (NON inclus dans ECMA6, mais disponible pour Chrome, Edge, Firefox et Safari depuis fin 2017, voir canIuse )
MDN

    async function waitForPromise() {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

Ajout dû au commentaire: Une fonction asynchrone retourne toujours une promesse, et dans TypeScript cela ressemblerait à:

    async function waitForPromise(): Promise<string> {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }
12
Martin Meeser

Vous ne voulez pas faire attendre la fonction, car JavaScript est censé ne pas être bloquant. Au lieu de retourner la promesse à la fin de la fonction, la fonction appelante peut alors utiliser la promesse pour obtenir la réponse du serveur.

var promise = query.find(); 
return promise; 

//Or return query.find(); 
3
Trace

Vous n'utilisez pas réellement les promesses ici. Parse vous permet d'utiliser des rappels ou des promesses; votre choix.

Pour utiliser les promesses, procédez comme suit:

query.find().then(function() {
    console.log("success!");
}, function() {
    console.log("error");
});

Maintenant, pour exécuter des commandes une fois la promesse terminée, vous pouvez simplement l'exécuter dans le rappel de promesse dans l'appel then(). Jusqu'ici, ce serait exactement la même chose que les rappels réguliers.

Pour bien utiliser les promesses, c’est lorsque vous les enchaînez, comme ceci:

query.find().then(function() {
    console.log("success!");

    return new Parse.Query(Obj).get("sOmE_oBjEcT");
}, function() {
    console.log("error");
}).then(function() {
    console.log("success on second callback!");
}, function() {
    console.log("error on second callback");
});
2
mash

J'ai le même problème, donc je maintiens du code, le code nécessite un appel ajax pour traiter une autre tâche, voici mon code

this.bindChangeEvent = function () {
    //select all bind change
    this._select_all.bind('change', function () {
        console.log('All')
        if ($(this).is(":checked")) {
            ///todo: call ajax to get all ids
            var idsAllItem = pointer.getAllData();

            console.log(idsAllItem);
            console.log('Another todo');

Fonction Ajax

this.getAllData = function() {
    var promises = [];
    var def = new $.Deferred();
    return new Promise((resolve, reject) => {
        // AJAX request
        var url = '...';
        $.ajax({
            url: url,
            type: "get",
            async: true,
            data: {},
            dataType: "json",
            success: function (data) {
                console.log('Ajjax done');
                resolve(data)
            },
            error: function (err) {
                reject(err)
            }
        });
    })
};

et j'obtiens le résultat

Another todo
Output
Ajax Done

….

0
dungphanxuan