Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/412.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript $q、$http和结果的并行处理_Javascript_Angularjs - Fatal编程技术网

Javascript $q、$http和结果的并行处理

Javascript $q、$http和结果的并行处理,javascript,angularjs,Javascript,Angularjs,我使用Angular的$q异步执行多个$http post调用。这是很好的工作,所有的调用都在几乎相同的时间返回,在几毫秒内 问题是下一步是处理结果。我希望并行处理结果,但它们似乎在排队,一次处理一个 我已经粘贴了下面的代码,如果有人能为我指出正确的方向,告诉我如何确保并行处理结果,我将不胜感激。此代码基本上是SearchService,其“search”方法是控制器的入口点 var searchService = { searchOptions: {}, searchResul

我使用Angular的$q异步执行多个$http post调用。这是很好的工作,所有的调用都在几乎相同的时间返回,在几毫秒内

问题是下一步是处理结果。我希望并行处理结果,但它们似乎在排队,一次处理一个

我已经粘贴了下面的代码,如果有人能为我指出正确的方向,告诉我如何确保并行处理结果,我将不胜感激。此代码基本上是SearchService,其“search”方法是控制器的入口点

var searchService = {
    searchOptions: {},
    searchResults: {
        foos: [],
        bars: [],
        typeBs: [],
        typeAs: []
    },
    searchFacets: {
        foos: [],
        bars: [],
        typeBs: [],
        typeAs: []
    },
    processResults: function (object, start) {
        return function (response) {

            //var marker = +new Date();  // log end timestamp
            //var diff = marker - start;
            //console.log("start processing " + object.name + ": " + diff);

            ...cut for brevity...

            //marker = +new Date();  // log end timestamp
            //diff = marker - start;
            //console.log("finished processing " + object.name + ": " + diff);
        }
    },
    getSingleSearchParams: function (object) {
        return {
            searchPhrase: this.searchOptions.searchPhrase,
            type: object.typeId,
            facets: object.facets
        };
    },
    getSearchResults: function (object, start) {
        if (object.include)
            dataFactory.searchFactory.search(this.getSingleSearchParams(object)).success((this.processResults)(object, start));
        else {
            var message = object.name + " not selected for search";
            throw message;
        }
    },
    search: function () {
        var start = +new Date();
        var searches = {};
        if (this.searchOptions.foos.include) {
            searches.fooResults = this.getSearchResults(this.searchOptions.foos, start);
        }
        if (this.searchOptions.bars.include) {
            searches.barResults = this.getSearchResults(this.searchOptions.bars, start);
        }
        if (this.searchOptions.typeBs.include) {
            searches.typeBResults = this.getSearchResults(this.searchOptions.typeBs, start);
        }
        if (this.searchOptions.typeAs.include) {
            searches.typeAResults = this.getSearchResults(this.searchOptions.typeAs, start);
        }
        $q.all(searches);
    }
};
SearchFactory的“search”方法包含$http调用:

searchFactory.search = function (searchOptions) {
    return $http.post(searchUrl, searchOptions);
};
注释掉的代码显示了计时,这揭示了处理结果的串行性

start processing TypeBs: 162
finished processing TypeBs: 164
start processing TypeAs: 535
finished processing TypeAs: 535
start processing Foos: 553
finished processing Foos: 554
start processing Bars: 1616
finished processing Bars: 1617
您的HTTP请求正在并行运行。processResults函数是在HTTP请求返回后执行的,这就是为什么它们看起来是串行的。在此处添加日志行,然后查看发生的情况:

getSearchResults: function (object, start) {
    if (object.include)
        console.log("starting request for object %o", object); 
        // this is where the HTTP request is made
        dataFactory.searchFactory.search(this.getSingleSearchParams(object)).success((this.processResults)(object, start));
    else {
        var message = object.name + " not selected for search";
        throw message;
    }
},
顺便说一下,$q.all在代码中对您没有任何帮助。$q.all的好处是,它允许您在保证您的所有承诺都已解决之后做一些事情。但是,您将在每个请求返回后立即处理它

var promises = [
  $http.get('foo'), 
  $http.get('bar')
];

// At this point, both the HTTP requests have already fired, in parallel. $q.all isn't responsible for this.

$q.all(promises)
.then(function(responses){
  // If you to execute some logic that can only happen after both HTTP requests return, this is where you'd use $q.all.
});
如果只想在所有搜索完成后才处理搜索结果,那么将处理业务逻辑放在$q.all的回调中

编辑:我对您的代码进行了一点重构,使其使用$q.all


对每个处理使用$timeout。它将并行运行,或者在每个资源/承诺上使用success函数我已经在使用success函数了-这就是调用processResults的地方,或者是因为我试图传递对象并以参数的形式启动,因此让processResults返回函数?@Drammy,我认为您的代码是正确的。但是$q.all用于promise对象。它不是并行的,因为您的getSearchResults不返回承诺对象,然后它一个接一个地执行。谢谢-我已经知道processResults方法是串行运行的-如何使它们并行运行?我使用$q.all同时执行多个$http请求。从您的评论中,我假设还有另一种方法可以做到这一点?Drammy-您正在将Searchs对象传递给$q.all,它需要一个承诺数组。甚至搜索上的属性也不是承诺,因为getSearchResults不返回承诺,所以我不知道它如何以您当前使用它的方式工作。好的,我将更改搜索对象,使属性成为承诺。我不确定这会有什么不同,尽管它的工作方式和我预期的一样,会阻止对结果的串行处理。只是做了一次编辑,重构了你的代码。这对你有什么好处吗?
var searchService = {
  processResults: function(responses) {
    // responses is now an array of response objects. Do whatever you will with it here.
  },
  getSingleSearchParams: function(object) {
    return {
      searchPhrase: this.searchOptions.searchPhrase,
      type: object.typeId,
      facets: object.facets
    };
  },
  getSearchResults: function(object, start) {
    // No need to throw an error here. This is the only place you call this method, so you can guarantee that it was called with an object that was selected to search.
    // I've also added a `return` keyword, that actually returns a promise, and removed `processResults`. Process the reults after `$q.all`.
    return dataFactory.searchFactory.search(this.getSingleSearchParams(object));
  },
  search: function() {
    var self = this;
    var start = new Date();
    var promises = ['foos', 'bars', 'typeBs', 'typeAs'].reduce(function(promises, search) {
      if (self.searchOptions[search].include) {
        promises.push(self.getSearchResults(self.searchOptions[search], start))
      }
      return promises;
    }, []);
    return $q.all(promises)
    .then(this.processResults.bind(this));
  }
};