2015-12-29 2 views
4

Я пытаюсь сделать функцию details(), которая просматривает детали определенных событий (getdetails) на основе доступных событий. В приведенном ниже примере запрашиваются сведения о событиях с идентификаторами ZRGZZ, RGHER и GRFDZ. Эти данные должны быть размещены внутри одного массива (кредиты от Theodore's answer). Результатом должно быть то, что когда я вызываю details(), результирующий массив сохраняется, поэтому я могу использовать его позже.Asynchronous javascript issue

Проблема в том, что я не знаю, как я могу вернуть этот последний массив. console.log(JSON.stringify(res)); выполняется до завершения построения массива. Я знаю, что это, вероятно, что-то делать с асинхронным JS, но я просто не могу обернуть мою голову вокруг него ...

function details() 
{ 
    var res = { 
    "Result": "success", 
    "Key": "12345", 
    "Data": [{ 
     "ID": "ZRGZZ", 
     "lastChangedDate": "2015-12-03 11:14:27" 
    }, { 
     "ID": "RGHER", 
     "lastChangedDate": "2015-12-03 15:17:47" 
    }, { 
     "ID": "GRFDZ", 
     "lastChangedDate": "2015-12-03 05:25:11" 
    }] 
}; 

    var i = 0; 
    var tmp; 
    res.Data.map(function(val,i){ 

     getdetails(val.ID).then(function(data){ 
      tmp = JSON.parse(data); 
      console.log(tmp); 
      Object.keys(tmp.Data[0]).map(function(v,j){ 
       val[v] = tmp.Data[0][v]; 
       console.log(JSON.stringify(res)); //(*)the last res gives me the result I'm looking for 
      }); 

     }, function(error){ //error callback 
      console.log(error) 
     }); 


    }); 
console.log(JSON.stringify(res)); //this is executed before (*) 
} 
+0

Попробуйте следующее: https://jsfiddle.net/rayon_1990/ks3vxomu/ – Rayon

+0

Я вижу угловое в ваших тегах, если вы можете использовать угловые, очень легко сделать асинхронные вызовы с помощью $ http.get, который дает вам обещание (нужный вам объект) – luk492

+0

@RayonDabre, который, кажется, меняет структуру моих данных – binoculars

ответ

0

Ну вы уже используете обещание - см then в вашем коде, и если это угловая то then сам вернется отложенный обещание, так что вы можете сделать:

res.Data.map(function (val, i) { 
    getdetails(val.ID).then(function (data) { 
     tmp = JSON.parse(data); 
     Object.keys(tmp.Data[0]).map(function (v, j) { 
      val[v] = tmp.Data[0][v]; 
     }); 
    }, function (error) { //error callback 
     console.log(error) 
    }).then(function() { 
     console.log(JSON.stringify(res)); 
    }) 
}); 

EDIT: впрыснуть службы $q в контроллер или услугу

promises = []; 
res.Data.map(function (val) { 
    promises.push(getdetails(val.ID).then(function (data) { 
     tmp = JSON.parse(data); 
     Object.keys(tmp.Data[0]).map(function (v, j) { 
      val[v] = tmp.Data[0][v]; 
     }); 
    }, function (error) { //error callback 
     console.log(error) 
    })); 
}); 
$q.all(promises).then(function() { 
    console.log(JSON.stringify(res)); 
}); 

сейчас, когда все getdetails разрешены, вы можете console.log или делать все, что хотите, с данными

+0

Спасибо за ваш ответ! Это похоже на работу! Единственное, что не является идеальным, это то, что он 'console.log (JSON.stringify (res));' выполняется x раз (x - количество идентификаторов, которые он должен искать). – binoculars

+1

Я обновляю свой ответ с более сложным решением для решения этой проблемы. – maurycy

+0

Я попробовал ваш обновленный ответ, но теперь 'res' содержит только данные для первого события. – binoculars

1

Один из способов заключается в использовании async библиотеки, в частности, функция async.each или async.eachSeries. (. Вы можете использовать async.map, но в вашем случае, если вы на самом деле не отображения, но изменяя основные элементы массива непосредственно)

В частности, ваш код будет выглядеть следующим образом:

async.each(res.Data, function(val,callback){ 
    getdetails(val.ID).then(function(data){ 
     tmp = JSON.parse(data); 
     Object.keys(tmp.Data[0]).map(function(v,j){ 
      val[v] = tmp.Data[0][v]; 
     }); 
     callback(null); // Asynchronous code has finished without error 
    }, function(error){ //error callback 
     callback(error); // Asynchronous code has finished with error 
    }); 
}, function(error) { 
    // All asynchronous calls have finished 
    if(error) 
     console.log("Error", error); 
    else 
     console.log("Success", res); 
}); 

async.each будет работать много итераций одновременно, тогда как async.eachSeries будет запускать только одну итерацию одновременно.