在下一个函数

时间:2017-12-05 10:38:32

标签: javascript angularjs

我想结合两个异步函数调用的结果。我试图将其作为单独的功能。

$scope.showPage = function () {
    var base ="";
    var menu= "";
    service.getGUI('menu', function (reply) {
            if (reply.status === 200 && reply.data !== null) {                  
               menu = reply.data; 
            }
        });

    service.getGUI('base', function (reply) {
            if (reply.status === 200 && reply.data !== null) {                 
               base=reply.data;                 
        });

console.log("base:"+ base);
console.log("menu:"+ menu);
}

但控制台输出未按预期更新。我如何逐个执行并在第二个函数中使用第一个的结果。

3 个答案:

答案 0 :(得分:0)

const asyncFunction = (x, cb) => setTimeout(cb.bind(null, x), 100 * Math.random())

// What you have
asyncFunction('Async 1', console.log)
asyncFunction('Async 2', console.log)

asyncFunction('Async 3', (x) => {
  console.log(x)
  asyncFunction('Async 4', console.log)
})
.as-console-wrapper { max-height: 100% !important; top: 0; }

如您所见,Async 1/2值每次都以不同的顺序打印,但Async 4始终在Async 3之后打印。

答案 1 :(得分:0)

您的调用都是异步的,因此函数的完成顺序没有一致性。您可以使用promise reduce模式完成等待,直到两者都被解析,然后再访问数据。虽然当你处理20多个异步调用时,承诺减少可能看起来不是最好的,但你会欣赏不必继续嵌套。

$scope.showPage = function () {
  var results = { base: "", menu: "" };

  ['menu', 'base'].reduce(function(acc, current) {
    return acc.then(new Promise(function(resolve, reject) => {
      service.getGUI(current, function (reply) {
        if (reply.status === 200 && reply.data !== null) {                  
           results[current] = reply.data; 
           resolve(results);
        } else {
           reject("error")
        }
      });
    }));
  }, Promise.resolve()).then(function(res) {
    console.log(res.menu, res.base);
  }).catch(function(e) { 
    console.log('errors have occured', e); 
  });
}

答案 2 :(得分:0)

将基于回调的API转换为基于承诺的API:

function getGUIpromise(item) {
    var deferredItem = $q.defer();
    service.getGUI(item, function (reply) {
        if (reply.status === 200 && reply.data !== null) {                  
            deferredItem.resolve(reply.data); 
        } else {
            deferredItem.reject("Error with getGUI "+item);
        };
    });
    return deferredItem.promise;
}

然后使用$q.all等待承诺:

$scope.showPage = function () {
    var basePromise = getGUIpromise("base");
    var menuPromise = getGUIpromise("menu");

    $q.all({base: basePromise, menu: menuPromise})
    .then(function(result) {
        console.log("base:"+ result.base);
        console.log("menu:"+ result.menu);
    }).catch(function(error) {
        console.log(error);
    });  
};

或者,如果在引擎盖下,service.getGUI方法使用基于承诺的API,则应返回并使用原始的底层承诺。