0
var p1;
var p2;
var service;
var list=[];

.........

service.call(p1,call_back);
service.call(p2,call_back);
//then do sth with the list

funciton call_back(results) {
    list.concat(results);
}

I want to call the service with p1 and p2, each time the service return some values and I put those into list. I want to wait for these two service finished, i.e. the values are all prepared in the list, then do sth. with that list.

I'm not familiar with java script asynchronous approach. I've tried Promise, but didn't work, anyone can write a simple demo for me?

add: I post my actual code, and please help me figure my problem..

    let place1 = auto1.getPlace();
    let place2 = auto2.getPlace();
    if (!place1.geometry || !place2.geometry) {
        let wrong_place_name = place1.geometry ? place2.name : place1.name;
        window.alert("No details available for input: '" + wrong_place_name + "'");
        return;
    }
    let job1 = new Promise(function () {
        service.nearbySearch({
            location: place1.geometry.location,
            radius: 20000,
            type: ['real_estate_agency']
        }, nearby_search_callback);
    });
    let job2 = new Promise(function () {
        service.nearbySearch({
            location: place2.geometry.location,
            radius: 20000,
            type: ['real_estate_agency']
        }, nearby_search_callback);
    });

    Promise.all([job1, job2]).then(function () {
        console.log('test');
        let agency_arr = Array.from(agency_list.values());
        console.log(agency_arr.length);
        agency_arr.sort(function (x, y) {
            let total_dist1 = dist(x.geometry.location, place1.geometry.location) + dist(y.geometry.location, place1.geometry.location);
            let total_dist2 = dist(x.geometry.location, place2.geometry.location) + dist(y.geometry.location, place1.geometry.location);
            return total_dist1 - total_dist2;
        });
        agency_arr.map(createMarker);
    });

The problem is the my code can never run to the Promise call back function

add: the nearby_search_callback is just fetch the data return by service and put them into a map.

function nearby_search_callback(results, status) {

    if (status === google.maps.places.PlacesServiceStatus.OK) {
        results.map(function (a) {
            agency_list.set(a.id, a);
        });
        // console.log(agency_list.size);
    }
}
Ziqi Liu
  • 2,931
  • 5
  • 31
  • 64

3 Answers3

1

You're just declaring promises and not doing anything with them. You need to resolve or reject them for them to ever complete.

I don't know what your "nearby_search_callback" function looks like, but it needs to do something like this instead, assuming it's a well structured callback that takes 2 parameters like (err, response), and eventually returns the data you want to return in the promise:

let job1 = new Promise(function (resolve, reject) {
    service.nearbySearch({
        location: place1.geometry.location,
        radius: 20000,
        type: ['real_estate_agency']
    }, function(err, data) { 
        if (err) reject(err);
        resolve(nearby_search_callback(null, data));
    });
});
bryan60
  • 28,215
  • 4
  • 48
  • 65
  • I'm pretty sure the `nearby_search_callback` should be omitted altogether (or, if at all, put in a `then` callback). Just only `resolve` there. – Bergi Nov 12 '17 at 21:37
  • it definitely shouldn't be put in a then statement, but it's possible it should just be omitted. I don't know if it transforms the data or provides some other desired side effect though. It looks to me like he stores the value statefully somewhere and then uses them in the promise result rather than returning directly. This isn't what I would recommend, but I guess it would work. – bryan60 Nov 12 '17 at 21:39
  • Yes, it definitely should be put as `job1 = job1.then(nearby_search_callback)`. The advantage: when it throws, the error will reject the promise instead of being ignored – Bergi Nov 12 '17 at 21:45
  • that is the explicit promise construction anti pattern and should be avoided: https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it the error here is not ignored, it is rejected explicitly in the callback. if the explicit rejection doesn't catch it, then the callback wouldn't have either. – bryan60 Nov 12 '17 at 21:46
  • You must be misunderstanding me. `job1` is the `new Promise`, not something returned by `service.nearbySearch` (which would indeed be the `Promise` constructor antipattern - believe me, [I know what I'm talking about](https://stackoverflow.com/a/25569299/1048572) :D) – Bergi Nov 12 '17 at 21:49
  • maybe I am misunderstanding what you're saying, but there still is no reason to put in nested "then" statements, which I believe also should be avoided, the error is explicitly rejected. The only reason I included the search callback was because I thought it might transform or produce other side effects. I just didn't have enough code to be sure. – bryan60 Nov 12 '17 at 21:51
  • The `.then(nearby_search_callback)` should not be *nested* inside the `new Promise`, but *chained* onto it – Bergi Nov 12 '17 at 21:55
  • which is then nested inside of the Promise.all()... regardless this is kind of futile because we don't know what the function even does or if it's needed at all. based on the code, probably sets some stateful variable which is bad form to begin with, it should just return direct – bryan60 Nov 12 '17 at 21:57
  • The nearby_search_callback is fetching the data return by service and put them into a map. i've added the code for nearby_search_callbakc. The service is google place api serivce. – Ziqi Liu Nov 12 '17 at 22:20
  • @bryan60 I got your idea, I need to somehow call the resolve inside the Promise executor, in order to inform that the promise job has been done. – Ziqi Liu Nov 12 '17 at 22:39
0

Use Promise and Promise.all. You can also use async-await.

const asyncronized = thing => new Promise((resolve, reject) => {
    service.call(thing, resolve);
});
// Asynchronize them.

Promise.all([asyncronized(p1), asyncronized(p2)]).then(final_callback);
// Go!
0

For future folks stuck on this. You can resolve and reject the promise like this:

const job1 =  new Promise(
      (
          resolve: (result: google.maps.places.PlaceResult[]) => void,
          reject: (status: google.maps.places.PlacesServiceStatus) => void
      ) => {
        placesService.findPlaceFromQuery(nameRequest, (results, status) => {
              if (status == google.maps.places.PlacesServiceStatus.OK) {
                  resolve(results);
              } else {
                  reject(status);
              }

          });
      });

const allResults = await Promise.all([job1, ...]);
pyron_orion
  • 545
  • 5
  • 18