2016-05-15 18 views
0

非同期呼び出し(geocode.reverseGeocode)を待つことはできますか?ディレクトリ内のJPGファイルをループし、そのEXIFデータから緯度&の経度を取得し、ジオコードを逆にして、その写真が撮影された場所から国/都市を取得します。最後に、ファイルにOSXタグを追加する必要があります。しかし、すべてのタグを取得するには、NodeJSスクリプトを複数回実行する必要があります。 (ファイルイテレータはジオコードプロセスを待たないので)。このリクエストを待つ最善の解決策は何ですか?NodeJSの同期ジオコーディング

あなたがここに私のコードを見つけることができます。事前

+0

まさにこのような問題に対処するための[async'](https://www.npmjs.com/package/async)という素敵なnpmパッケージがあります。 –

+0

なぜ待つ?ブルーバードの約束を使用してください。 Promise.mapはリクエストを抑制することさえできます。啓発を求める。 – Wainage

+0

[非同期呼び出しからの応答を返すにはどうすればいいですか?](http://stackoverflow.com/q/14220321/218196) –

答えて

2

https://github.com/Acoustics/jbTagify/blob/development/index.js

おかげで、複数の非同期呼び出しを処理するための簡単な方法は、約束を使用するのだろう、と同期して実行し、待つ必要はありません1つは終了する。 Nodeで利用可能なネイティブ・プロミスを使用するか、bluebirdなどの約束ライブラリを使用することができます。他の非同期操作を実行するライブラリを約束することができます。

最も簡単なユースケースは次のようになりますが、解決された値として返されたデータとの約束を返すpromisified機能geocodeAsync(元の関数名+ Async)を使用

var Promise = require("bluebird"); 
var geocoder = Promise.promisifyAll(require('geocoder')) 

geocoder.geocodeAsync("Atlanta, GA") 
.then(function(data){ 
    var lat = data.results[0].geometry.location.lat; 
    var lng = data.results[0].geometry.location.lng; 
    console.log("Coordinates for Atlanta, GA: " + lat + "," + lng); 
}); 

複数の非同期コードを実行する場合は、一連の約束事を簡単に作成し、すべての約束事が解決されたときに結果を処理することができます。

var citiesToGeocode = ["Miami, FL", "New York", "Orlando, FL", "Rio de Janeiro, Brazil"]; 
var geocodePromises = []; 
for (var i = 0; i < citiesToGeocode.length-1; ++i) { 
    geocodePromises.push(geocoder.geocodeAsync(citiesToGeocode[i])); 
} 

Promise.all(geocodePromises).then(function(result) { 
    result.forEach(function(geocodeResponse){ 
     console.log("Coordinates for " + geocodeResponse.results[0].formatted_address +": " + geocodeResponse.results[0].geometry.location.lat + "," + geocodeResponse.results[0].geometry.location.lng); 
    }); 
}); 

同じアプローチを使用して、reverseGeocodeAsyncを使用して座標から情報を検索できます。

+0

ありがとうございます!私はそれの背後にあるアイデアを得るが、別のコールバック(新しいexifからのコールバック)の中で "geocodePromises.push"を呼び出す必要がある。私はjpgでディレクトリ(async)をループし、新しいexif(async)でexif-dataを取得し、最後にpromises-array(fs.readDirの外側)に約束を追加したい。私の機能Promise.allでは、私は各約束をループして、位置データとファイル名を保持したいと思っています。どのように私はそれを行うことができますか? (私はpromise.promisifyAllをrequire( 'exif')の周りでラップしようとしました。ExifImageしかし成功なし。 –

+0

'exif'パッケージは非同期コードで動作していないようです。なぜあなたはそれを約束しますか?Promise.allは結果を配列に解決します。あなたがループして何でもしたいことをすることができます。 –

+0

あなたは私の日を保存しました:) –

0

これは私のコードです。ご覧のとおり、私はルートレベルで約束を集める必要があります。私の目的は、ジオコーディングされたデータを含むファイル名を含む約束の集まりを得ることです。

var 
    _ = require('lodash'), 
    path = require('path'), 
    pkg = require(path.join(__dirname, 'package.json')), 
    fs = require('fs'), 
    promise = require('bluebird'), 
    exif = require('exif').ExifImage, 
    geocoder = promise.promisifyAll(require('geocoder')), 
    exec = require('child_process').exec, 
    config = require('nconf').file({ 
     file: path.join(__dirname, 'config.json') 
    }); 

var geocodePromises = []; // I want to collect all promises here 

fs.readdir(path.join(__dirname, 'files'), function (err, files) { 
    files.filter(function (file) { 
     var ext = file.split('.').pop(), 
      cond; 

     cond = file; // File needs to exist 
     cond = cond && file[0] != '.'; // Exclude hidden files 
     cond = cond && config.get("files:support").indexOf(ext) > -1; // File needs to be supported 

     return cond; 
    }).forEach(function (file) { 
     file = path.join(__dirname, 'files/') + file; 

     new exif({ 
      image: file 
     }, function (err, data) { 
      if (!err) { 
       if (data.gps) { 
        var location = parseGPS(data.gps); // Obtain lat & lng 

        geocodePromises.push(geocoder.reverseGeocodeAsync(location.lat, location.lng)); 
       } else { 
        console.log("Error: GPS data not available"); 
       } 
      } else { 
       console.log("Error: " + err); 
      } 
     }); 
    }); 

    Promise.all(geocodePromises).then(function (result) { 
     console.log(result); // Returns an empty array [] 
     // Each result should contain the filename and geocoded location 

     /* 
      Example: 

      { 
       "file": "1.jpg", 
       "location": { 
        <google reverseGeocode object> 
       } 
      } 
     */ 
    }); 

    //exec('killall Finder'); 
}); 

function parseGPS(gps) { 
    var lat = gps.GPSLatitude, 
     lng = gps.GPSLongitude, 
     latRef = gps.GPSLatitudeRef || "N", 
     lngRef = gps.GPSLongitudeRef || "W"; 

    // Convert coordinates to WGS84 decimal 
    lat = (lat[0] + lat[1]/60 + lat[2]/3600) * (latRef == "N" ? 1 : -1); 
    lng = (lng[0] + lng[1]/60 + lng[2]/3600) * (lngRef == "W" ? -1 : 1); 

    // Return lat, lng 
    return { 
     lat, 
     lng 
    }; 
}; 
+0

追加情報、質問の編集、回答の投稿はしないでください。 –

+0

私の例を挙げて、誰かが私にこのことをどうやって説明することができますか? –