2017-09-19 3 views
0

私はforループを使用して、配列の要素に対して反復処理を行い、forループ内の異なるパラメータで同じ関数を呼び出します。ここに私のコードです:forループの各反復を待って、nodeJSのAPIレスポンスとして応答を返す方法

exports.listTopSongs = function(query) { 
    return new Promise(function(resolve, reject) { 
     var str = query.split(","), category, 
     for(var i=0; i<str.length; i++) { 
      sampleFn(str[i], 'sample', resolve, reject); 
     } 
    }); 
}; 

function sampleFn(lang, cat, resolve, reject) { 
     client.on("error", function (err) { 
      console.log(err); 
      var err = new Error('Exception in redis client connection') 
      reject(err);         
     }); 
     client.keys(lang, function (err, keys){ 
      if (err) return console.log(err); 
      if(keys.length != 0) { 
       client.hgetall(keys, function (error, value) { 
        var objects = Object.keys(value); 
        result['title'] = lang; 
        result[cat] = []; 
        var x =0; 
        for(x; x<objects.length; x++) { 
         var val = objects[x]; 
          User.findAll({attributes: ['X', 'Y', 'Z'], 
           where: { 
            A: val 
           } 
          }).then(data => { 
           if(data != null) { 
            //some actions with data and stored it seperately in a Json array 
            if(result[cat].length == objects.length) { 
             resolve(result); 
            } 
           } else { 
            console.log(""+cat+" is not avilable for this value "+data.dataValues['X']); 
           } 
          }); 
        } 
       }); 
     }); 
    } 

ここでは、最初の反復の完了を待つことはありません。それは最初の反復機能を完了する前に非同期的に実行されます。結果として結果を返す必要があります:[{1、2}、{3,4}]。シームレスに実行され、すべてを完了する前に空のオブジェクトまたは1つのオブジェクトのみを返します。それを解決する方法。

node-async-loopを使用しました。しかし、それは次を使用し、私はそのパッケージを使用している間私のパラメータを送信することができません。助けてください

+0

"aync"パッケージを確認してください。これは、ループを同期して実行する多くの機能を備えています。 –

+0

あなたはどのノードのjsバージョンを使用していますか? –

+0

私はノード8.4.0を使用しています –

答えて

1

Asyncはそうすることを可能にするコントロールフローメソッドを提供します。

async.each(openFiles, function(file, callback) { 

    // Perform operation on file here. 
    console.log('Processing file ' + file); 

    if(file.length > 32) { 
     console.log('This file name is too long'); 
     callback('File name too long'); 
    } else { 
     // Do work to process file here 
     console.log('File processed'); 
     callback(); 
    } 
}, function(err) { 
    // if any of the file processing produced an error, err would equal that error 
    if(err) { 
     // One of the iterations produced an error. 
     // All processing will now stop. 
     console.log('A file failed to process'); 
    } else { 
     console.log('All files have been processed successfully'); 
    } 
}); 
+0

あなたはasync.eachを使って自分のコードを修正してください。 –

0

ライブラリを使用しない場合、あなたはそれを自分でコーディングすることができます:async.eachを使用して

。それはまた非常に有益なものになります。私はあなたの問題を取り、ダミーの非同期ループをコード化:

function listTopSongs(query) { 
 
    return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls 
 
     const str = query.split(",") //str is const, and the other variable was not used anyway 
 
     
 
     for(let i = 0;i < str.length; i++) { 
 
      const planet = await sampleFn(str[i], 'sample', resolve, reject) 
 
      console.log(planet) 
 
     } 
 
    }); 
 
}; 
 

 
function sampleFn(a, b, c, d) { 
 
    return fetch(`https://swapi.co/api/planets/${a}/`) 
 
     .then(r => r.json()) 
 
     .then(rjson => (a + " : " + rjson.name)) 
 
} 
 

 
listTopSongs("1,2,3,4,5,6,7,8,9")

私は偽の長い約束にいくつかのダミースターウォーズのAPIを使用しますが、それはあなたのsampleFnで動作するはずです。例のようなネットワークコールがあれば、非常に遅いことに注意してください。 EDIT

私はあなたのコードを実行し、私はいくつかのミスがあります気づいた:それはthenableではありませんので、あなたの約束には決意がない

ここ

で完全に動作するコード(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolveがthenableを参照してください) 。素敵な部分は必要ありません:ライブラリは必要ありません。

//for node.js, use node-fetch : 
 
//const fetch = require("node-fetch") 
 

 
function listTopSongs(query) { 
 
    return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls 
 
     const str = query.split(",") //str is const, and the other variable was not used anyway 
 
     const planets = [] 
 
     for (let i = 0; i < str.length; i++) { 
 
      const planet = await sampleFn(i + 1, str[i], resolve, reject) 
 
      planets[i] = planet 
 
      console.log(planet) 
 
     } 
 
     resolve(planets) 
 
    }); 
 
}; 
 

 
function sampleFn(a, b, c, d) { 
 
    return fetch(`https://swapi.co/api/planets/${a}/`) 
 
     .then(r => r.json()) 
 
     .then(rjson => (a + b + " : " + rjson.name)) 
 
} 
 

 
listTopSongs("a,b,c,d").then(planets => console.log(planets))

+0

json配列を関数sampleFnからlistTopSongsに戻すことができません。 –

0

あなたが約束を使用しているので、あなたは、外部に依存しないようにごsampleFnを変更する必要があり、これが機能するために、この

exports.listTopSongs = function(query) { 
    return Promise.resolve(true).then(function(){ 
     var str = query.split(","); 
     var promises = str.map(function(s){ 
      return sampleFn(str[i], 'sample'); 
     }); 
     return Promise.all(promises); 
    }).then(function(results){ 
     //whatever you want to do with the result 
    }); 
}; 

ような何かを行うことができます解決し、拒否する機能。私は、外部からの解決と拒否を使用する理由は見ません。なぜちょうど使用しないPromise.Resolve、Promise.Reject;

関連する問題