按顺序连续处理项目列表,并在所有完成后返回 ok(异步 -> 同步)
Processing list of items serially in order and returning ok when all is done (async -> sync)
我对 promises 和异步过程的概念感到头疼。我已经订购了一个列表,想为每个项目调用一个函数,等到第一个项目的第一个过程完成,继续第二个、第三个等等。只有在处理完每个项目后我才想继续主流程。
下面是与主进程配合良好的代码。因此返回 Q.all(promises) 导致首先处理所有承诺,然后继续主流程。但问题是,项目(导航键)是异步处理的,而我需要它们是同步的:
function processPages(that) {
var navs = [];
Object.keys(that.navigation).map(function(key) {
navs.push({key: key, order: parseInt(that.navigation[key].index)});
});
var promises = navs.sort(function(a, b) {
return a.order - b.order;
})
.map(function(item) {
return that.parsePage(item.key).then(function(page) {
return page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that);
});
});
});
return Q.all(promises);
}
下面是我修改项目同步和正确顺序处理时的代码,但现在主进程将不同步:
function processPages(that) {
var navs = [];
Object.keys(that.navigation).map(function(key) {
navs.push({key: key, order: parseInt(that.navigation[key].index)});
});
var promises = navs.sort(function(a, b) {
return a.order - b.order;
})
.reduce(function(previous, item) {
return previous.then(function () {
return that.parsePage(item.key).then(function(page) {
return page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that);
});
});
});
}, Q());
return Q.all(promises);
}
有谁知道这里发生了什么以及在这种情况下如何正确使用 promises?
附加信息
processPages 从 init 挂钩调用。如果不使用 promise (Q.all),那么 page hook 可能会在 init hook 完全处理之前触发,我也不允许这样做。这就是我所指的 "main process".
module.exports =
{
hooks: {
"init": function() {
var options = this.options.pluginsConfig['regexplace'] || {};
options.substitutes = options.substitutes || {};
// collects text replacement queries from plugin configuration
options.substitutes.forEach(function (option) {
patterns.push({re: new RegExp(option.pattern, option.flags || ''),
sub: option.substitute,
decode: option.decode || false,
store: option.store || null,
unreset: option.unreset || false});
});
this.config.book.options.variables = this.config.book.options.variables || {};
processPages(this);
},
"page": function(page) {
var that = this;
// process all normal sections in page
page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that, true);
});
return page;
}
}
};
代码是 GitBook 插件代码的一部分。
查看 Understanding JavaScript Promise with Examples 中的可运行示例(来自 Chrome 的开发控制台),尤其是 "chaining" 示例。
根据您对 的描述“...我已经订购了一个列表并想调用一个包含每个项目的函数,等到第一个过程第一项完成后,进行第二项、第三项,依此类推。只有在处理完每一项后,我才想继续 主流程。",
从算法的角度来看,你应该 "chaining" 多个承诺在一起:
- 为每个项目创建一个 Promise。当一个项目完成时,调用 resolve() 以便 then() 将执行(链中的下一个项目)。
- 将 "main process" 作为链中的最后一项。
推荐你 test/learn promises 的执行流程,在将它应用到你的问题之前用简单的例子 - 使它更容易理解。
希望对您有所帮助! :-)
解决方案很简单,只需更改:
processPages(this);
至
return processPages(this);
在初始化挂钩上。
我对 promises 和异步过程的概念感到头疼。我已经订购了一个列表,想为每个项目调用一个函数,等到第一个项目的第一个过程完成,继续第二个、第三个等等。只有在处理完每个项目后我才想继续主流程。
下面是与主进程配合良好的代码。因此返回 Q.all(promises) 导致首先处理所有承诺,然后继续主流程。但问题是,项目(导航键)是异步处理的,而我需要它们是同步的:
function processPages(that) {
var navs = [];
Object.keys(that.navigation).map(function(key) {
navs.push({key: key, order: parseInt(that.navigation[key].index)});
});
var promises = navs.sort(function(a, b) {
return a.order - b.order;
})
.map(function(item) {
return that.parsePage(item.key).then(function(page) {
return page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that);
});
});
});
return Q.all(promises);
}
下面是我修改项目同步和正确顺序处理时的代码,但现在主进程将不同步:
function processPages(that) {
var navs = [];
Object.keys(that.navigation).map(function(key) {
navs.push({key: key, order: parseInt(that.navigation[key].index)});
});
var promises = navs.sort(function(a, b) {
return a.order - b.order;
})
.reduce(function(previous, item) {
return previous.then(function () {
return that.parsePage(item.key).then(function(page) {
return page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that);
});
});
});
}, Q());
return Q.all(promises);
}
有谁知道这里发生了什么以及在这种情况下如何正确使用 promises?
附加信息
processPages 从 init 挂钩调用。如果不使用 promise (Q.all),那么 page hook 可能会在 init hook 完全处理之前触发,我也不允许这样做。这就是我所指的 "main process".
module.exports =
{
hooks: {
"init": function() {
var options = this.options.pluginsConfig['regexplace'] || {};
options.substitutes = options.substitutes || {};
// collects text replacement queries from plugin configuration
options.substitutes.forEach(function (option) {
patterns.push({re: new RegExp(option.pattern, option.flags || ''),
sub: option.substitute,
decode: option.decode || false,
store: option.store || null,
unreset: option.unreset || false});
});
this.config.book.options.variables = this.config.book.options.variables || {};
processPages(this);
},
"page": function(page) {
var that = this;
// process all normal sections in page
page.sections.filter(function(section) {
return section.type == 'normal';
})
.map(function(section) {
collectStore(section, page, that, true);
});
return page;
}
}
};
代码是 GitBook 插件代码的一部分。
查看 Understanding JavaScript Promise with Examples 中的可运行示例(来自 Chrome 的开发控制台),尤其是 "chaining" 示例。
根据您对 的描述“...我已经订购了一个列表并想调用一个包含每个项目的函数,等到第一个过程第一项完成后,进行第二项、第三项,依此类推。只有在处理完每一项后,我才想继续 主流程。",
从算法的角度来看,你应该 "chaining" 多个承诺在一起:
- 为每个项目创建一个 Promise。当一个项目完成时,调用 resolve() 以便 then() 将执行(链中的下一个项目)。
- 将 "main process" 作为链中的最后一项。
推荐你 test/learn promises 的执行流程,在将它应用到你的问题之前用简单的例子 - 使它更容易理解。
希望对您有所帮助! :-)
解决方案很简单,只需更改:
processPages(this);
至
return processPages(this);
在初始化挂钩上。