嵌套异步函数嵌套同步函数
Make Nested Async Functions Nested Sync Functions
我正在开发一个chrome扩展,使用两个嵌套的异步函数。然而,我希望函数是同步的,但没有一个参数,使它同步,API只有async选项。如果可能的话,我需要这两个函数具有嵌套同步函数行为。告诉我你能不能理解。以下是代码的主要部分:
// Track the number of callbacks from chrome.history.getVisits()
// that we expect to get. When it reaches zero, we have all results.
chrome.history.search({
'text': '', // Return every history item....
'startTime': oneWeekAgo, // that was accessed less than one week ago.
'maxResults': 999999999
},
function (historyItems) {
// For each history item, get details on all visits.;
for (var i = 0; i < historyItems.length; ++i) {
Edited - 0 - I need some code here too.
chrome.history.getVisits({url: historyItems[i].url}, function (visitItems) {
//1 - I want this to happen first, but it happens after 2
for (var j = 0; j < visitItems.length; ++j) {
//Do something that depends on the first function
}
})
//2 -i want this to happen second and after 1, but it happens first, since chrome.history.getvisits is async.
}
//3- I want this to happen third, when the two loops are complete.
})
JavaScript本质上是单线程的,而"异步"意味着"事件队列后面的某个地方",真的。
正因为如此,没有办法等到异步任务结束:你必须停止运行以启动下一个异步任务。唯一的方法是在异步任务结束时添加要调用的代码,称为异步(或回调)链接。
然而,值得庆幸的是,有一些框架可以帮助您以更有组织的方式构建这些东西。其中一个框架就是Promises。我将让你访问该链接以获得基本介绍。
首先,让我们"承诺"所需的API调用。第一个:
function historyLastWeek() {
return new Promise(function(resolve, reject) {
chrome.history.search({
'text': '',
'startTime': oneWeekAgo, // don't forget that part
'maxResults': 999999999
}, function(historyItems) {
if(chrome.runtime.lastError) {
reject(chrome.runtime.lastError.message);
} else {
resolve(historyItems);
}
});
});
}
上面的代码返回一个Promise,它将运行chrome.history.search
API调用,或者用历史条目解析,或者用错误消息拒绝。
Promise的意义在于你可以在它上面使用.then()
,链接调用。
让我们也承诺chrome.history.getVisits
(注意,它需要一个历史项,因为我们想要):
function getVisits(historyItem) {
return new Promise(function(resolve, reject) {
chrome.history.getVisits({url: historyItem.url}, function(visitItems) {
if(chrome.runtime.lastError) {
reject(chrome.runtime.lastError.message);
} else {
resolve({
historyItem: historyItem, // let's keep track of it
visitItems: visitItems
});
}
});
});
}
所以,我们有两个承诺返回一个数组的结果。如何将它们联系在一起?
首先,我假设你没有打破内部循环(所以我"并行"运行"getvisitors")。我们用Promise.all
表示。让我们看看. .
historyLastWeek().then(function(historyItems) {
return Promise.all(
// map() returns the array of results of applying a function
// to all members of the array
historyItems.map(getVisits)
);
}).then(function(results) {
// results is an array of objects
results.each(function(result) {
// here, result.historyItem is the history item,
// and result.visitItems is an array of visit items
/* here goes your code #1 */
result.visitItems.each(function(visitItem) {
/* here goes your "Do something that depends on the first function" code */
});
/* here goes your code #2 */
});
/* here goes your code #3 */
}).catch(function(errorMsg) {
// oh noes
});
如果你需要在代码#3之后做一些事情,那么你也需要承诺最后一个函数,并添加另一个.then()
。
这段代码有一个不幸的属性:由于JavaScript并不懒惰,all()
将在执行任何代码之前将所有结果收集到一个单一的、整体的二维数组中,并且您不能过早地中断内部循环。
您可以将其修改为顺序执行,而不是收集数组然后处理它。
historyLastWeek().then(function(historyItems) {
return historyItems.reduce(function(sequence, historyItem) {
return sequence.then(function() {
return getVisits(historyItem);
).then(function(result) {
// here, result.historyItem is the history item,
// and result.visitItems is an array of visit items
/* here goes your code #1 */
result.visitItems.each(function(visitItem) {
/* here goes your "Do something that depends on the first function" code */
});
/* here goes your code #2 */
// Gotta return some promise
return Promise.resolve();
});
}, Promise.resolve());
}).then(function() {
/* here goes your code #3 */
}).catch(function(errorMsg) {
// oh noes
});
查看上面的链接,了解所有这些是如何工作的。
它是否比非promise代码更容易或更干净是有争议的,但至少它是手动链接回调的另一种选择。
如果您想支持32之前的Chrome版本,其中引入了承诺,您唯一可以做的就是将代码2
和3
移动到内部回调:
function (historyItems) {
var lastItemIndex = historyItems.length - 1;
for (var i = 0; i <= lastItemIndex; ++i) {
chrome.history.getVisits({url: historyItems[i].url}, function(visitItems) {
// 1
for (var j = 0; j < visitItems.length; ++j) {
//Do something that depends on the first function
}
// 2
......................
if (i == lastItemIndex) {
// 3
......................
}
})
}
})
- 用嵌套函数和默认函数定义函数
- d3中堆栈函数和嵌套函数之间的差异
- JavaScript 中的嵌套函数和 “this” 关键字
- 嵌套到另一个函数中的Fancybox函数;不起作用
- Javascript中带有返回值的嵌套函数
- 访问嵌套函数结构中的JavaScript父函数变量
- 从嵌套函数访问函数属性
- 如何在javascript中使用嵌套函数作为生成器(使用“inner”yields)
- Javascript嵌套函数属性继承
- 具有嵌套对象数组的 Javascript 对象的递归搜索函数
- Facebook Javascript 函数嵌套循环
- 将动态 AJAX 函数嵌套在 JavaScript 函数中 - 并保持更新
- 对由多个groupBy函数嵌套的对象数组进行分组
- 从父函数返回什么以获取从子函数/嵌套函数返回的值
- jQuery匿名函数-嵌套函数
- ajax调用函数嵌套
- 函数嵌套括号的Python风格指南是什么?
- setTimeout函数中的关键字,该函数嵌套在on()方法下.但这并没有奏效
- 嵌套异步函数嵌套同步函数
- 如何克服函数嵌套