具有2个回调的异步javascript - 如何?

时间:2015-05-19 20:14:35

标签: javascript asynchronous callback

我需要像这样流动的代码:从calcRoute获取值(google maps distance) - >添加到数组(?)/添加到输出字符串,直到它已遍历所有值。然后附加到listview。

var myArray = [];
$.get( "http://www.url.com/info.php", function( data ) {

        var output = "";
        var imgsrc = "";

         obj = jQuery.parseJSON(data);


        for (i = 0; i < obj.length; i++) 
            { 

                store=obj[i].store;

            for (j = 0; j < obj[i].products.length; j++) 
                { 
                    productname= obj[i].products[j].productname;
                    price=obj[i].products[j].price;

                    calcRoute(function(returnValue) {

                        myArray.push(returnValue);
                        console.log("Inside callback : " + flowcounter++);
                        console.log("Inside callback (Array): " + myArray);
                    }); 

                    console.log("Array has now (J-loop) : " + myArray);
                    console.log("Flowcounter has now (J-loop) : " + flowcounter++);
                    output+='<li> <img style="margin-left: 8px" width="80" height="80" alt="sample" src="img/logo.png" align="left"/> <h3>'+ productname+' '+price+'</h3><p>Ca:'+ myArray[i] +' km.</p> </li>';                 
                }

            }


        console.log("Append to list (Counter) : " + flowcounter++);
        console.log("Appen to list(Array): " + myArray);
        $("#prodlist").append(output).listview().listview('refresh');

            });

但是现在它是这样的:J-loop - &gt;附加到列表视图 - &gt; calcRoute。 因此在执行下一个操作之前它没有值。这里的问题显然是我需要得到一个值,把它放在输出中,当它们全部完成时,放入prodlist-append。 这是calcRoute代码:

        function calcRoute(callback) {

        var start = new google.maps.LatLng(55.613520,12.534539);
        var end = new google.maps.LatLng(55.713520,12.534539);

    var request = {
          origin: start,
          destination: end,
          travelMode: google.maps.TravelMode["DRIVING"]
      };
      directionsService.route(request, function(response, status) {
          if (status == google.maps.DirectionsStatus.OK) {
              directionsDisplay.setDirections(response);
          }
          var totalDistance = 0;
          var legs = response.routes[0].legs;
          for(var i=0; i<legs.length; ++i) {
             totalDistance += legs[i].distance.value;
          }
          totalDistance = totalDistance / 1000;
         totalDistance = totalDistance.toFixed(1);
         myArray.push(totalDistance);
         callback(totalDistance);
     });
    };

也添加了logcat:Logcat of flow

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:2)

请看Javascript Promises

它们允许您链接异步操作,例如:

doThing1().then(doThing2()).then(doThing3());

或者更适合您的目的,Promise.all会等到所有操作完成后再做下一件事:

Promise.all([
    doThing1(),
    doThing2(),
    doThing3()
]).then(addToList(results));

Here's a jsfiddle概述了你可能会在这里做的事情。我不确切地知道你要做什么,但希望它足以让你感动。

使用Javascript:

var storeData = [
    {
        name: 'Store 1',
        location: {
            lat: 55.613520,
            lng: 12.534539
        },
        products: [
            {
                productname: "Product 1",
                price: 1.10
            },
            {
                productname: "Product 2",
                price: 2.20
            }
        ]
    },
    {
        name: 'Store 2',
        location: {
            lat: 55.613520,
            lng: 12.634539
        },
        products: [
            {
                productname: "Product 1.1",
                price: 1.11
            }
        ]
    }
];

// wraps a jquery ajax request for store data in a Promise
function getStores() {
    return new Promise(function(fulfill, reject) {

        // this is a jsfiddle ajax request
        // that just returns the json you send it (storeData).
        $.post( '/echo/json/', {
            json: JSON.stringify(storeData),
            delay: 1
        })
        .done(function(result) {
            return fulfill(result);    
        })
        .fail(function(reason) {
            return reject(reason);
        });
    });
}

function calcRoute(store) {
    return new Promise(function(fulfill, reject) {
        // call google here. faking it for the fiddle.
        return fulfill({
            result: 'Fake route result for store ' + store.name
        });
    });
}

function getRoutes(stores) {
    var promises = [];
    for (var i = 0; i < stores.length; i++) {
        promises.push(calcRoute(stores[i]));
    }
    return Promise.all(promises);
}

function updateDisplay(routes) {
    var list = document.getElementById('list');
    for (var i = 0; i < routes.length; i++ ) {
        console.log(routes[i].result);
        $(list).append('<li>' + routes[i].result + '</li>');
    }
}

function go() {
    return getStores()
    .then(getRoutes)
    .then(updateDisplay)
    .catch(function(reason) {
        console.error('Error %O', reason);
    });
}

$.ready(go());

答案 1 :(得分:0)

您可以使用嵌套回调,或者使用某些框架,您可以使用promises链接.then或.success。这是一篇关于展平嵌套回调的有趣文章,以避免“回调地狱”http://solutionoptimist.com/2013/12/27/javascript-promise-chains-2/