我对Promises的概念还很陌生,我试图了解范围的工作原理。我基本上是试图将值从 then()内部存储到 Promise
之外的变量中下面是我用Nodejs(Express)写的一个简单函数,它使用Sequelize在数据库上运行查询。
exports.getTest = (req, res, next) => {
var categories = [];
var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
for (var i = 0; i < names.length; i++) {
model.Category.findOne({
where: {
name: names[i]
},
attributes: ['id']
}).then(id => {
categories.push(
{
category_id: id.id
});
});
}
res.json(categories);
}
此后,我还有其他逻辑要运行,并且在Promise周围有一个for循环。因此,我不能在then内运行我的下一个逻辑,否则由于for循环,它将使其多次运行。我需要填充数组类别以便在下一个操作中使用它。
当前,我的回复(res.json(categories)
)是[]
任何帮助将不胜感激。
PS:我知道这是一个常见的话题,但是正如我提到的,我对此很陌生,其他答案与我的情况不符,进一步使我感到困惑。
谢谢!
答案 0 :(得分:2)
在您的情况下,categories
将始终返回[]
,因为在返回响应之前,您不必等待所有诺言完成。对于For循环,在继续下一个迭代之前,请不要等待异步操作完成。因此,循环结束,并在其中任何一个结束之前返回响应。
应该在一个循环中调用promise,而不是在它们之间调用promise,然后将其传递给Promise.all()
函数。
这是它的外观
exports.getTest = () => {
var categories = [];
var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
var promiseArray = [];
for (var i = 0; i < names.length; i++) {
promiseArray.push(
model.Category.findOne({
where: {
name: names[i]
},
attributes: ['id']
}).then(id => {
categories.push(
{
category_id: id.id
});
});
)
}
return Promise.all(promiseArr)
}
getTest()
现在返回一个诺言,因此可以这样称呼
getTest()
.then(data => {
// data will be an array of promise responses
}).catch(err => {
console.log(err);
})
答案 1 :(得分:1)
您可以尝试Promise.all()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Promise.all()方法返回一个Promise,当作为可迭代对象传递的所有promise已解决或可迭代对象不包含promise时,该Promise进行解析。它以第一个承诺被拒绝的理由拒绝。
Incident Identifier: A450C98F-DDB4-4593-9C93-B4C17D3EB4E4
CrashReporter Key: DB1695E0-C812-4087-9567-D4BD5D4D491C
Hardware Model: iPhone8,1
Code Type: ARM-64
Parent Process: ??? [1]
Date/Time: 2019-05-26T17:01:50Z
Launch Time: 2019-05-26T17:01:37Z
OS Version: iPhone OS 12.1.2 (16C101)
Report Version: 104
Exception Type: SIGILL
Exception Codes: ILL_ILLTRP at 0x100c3343c
Crashed Thread: 0
Thread 0 Crashed:
0 CocoaLumberjack 0x0000000100c3343c CocoaLumberjack.asyncLoggingEnabled.unsafeMutableAddressor : Swift.Bool (CocoaLumberjack.swift:73)
1 XXXApp 0x0000000100762d08 XXXApp.XXXAppNavigationContext.append(XXXApp.XXXAppNavigationPathComponent) -> () (XXXAppNavigationContext.swift:0)
2 XXXApp 0x0000000100763a4c merged @objc XXXApp.XXXAppNavigationContext.append(XXXApp.XXXAppNavigationPathComponent) -> () + 44
3 XXXApp 0x000000010071ae80 -[XXXAppTableViewController viewWillAppear:] (XXXAppTableViewController.m:35)
4 XXXApp 0x0000000100708360 -[XXXAppGroupTableViewController viewWillAppear:] (XXXAppGroupTableViewController.m:83)
5 UIKitCore 0x00000001b3224f28 -[UIViewController _setViewAppearState:isAnimating:] + 580
6 UIKitCore 0x00000001b322560c -[UIViewController __viewWillAppear:] + 136
7 XXXApp 0x00000001006d3ff8 -[XXXAppTabBarViewController sendAppearanceTransitionsToViewControllers:] (XXXAppTabBarViewController.m:441)
8 XXXApp 0x00000001006d3d88 -[XXXAppTabBarViewController scrollViewDidScroll:] (XXXAppTabBarViewController.m:426)
9 XXXApp 0x00000001006d1458 -[XXXAppTabBarViewController viewDidLayoutSubviews] (XXXAppTabBarViewController.m:159)
10 UIKitCore 0x00000001b3c8f944 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1736
11 QuartzCore 0x000000018ac4db74 -[CALayer layoutSublayers] + 180
12 QuartzCore 0x000000018ac52b2c CA::Layer::layout_if_needed(CA::Transaction*) + 320
13 UIKitCore 0x00000001b3c7acc8 -[UIView(Hierarchy) layoutBelowIfNeeded] + 544
14 UIKitCore 0x00000001b318bd0c -[UINavigationController _layoutViewController:] + 1292
15 UIKitCore 0x00000001b3186400 -[UINavigationController _layoutTopViewController] + 232
16 UIKitCore 0x00000001b31845d0 -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] + 776
17 UIKitCore 0x00000001b3c4a7d4 -[UINavigationTransitionView _notifyDelegateTransitionDidStopWithContext:] + 416
18 UIKitCore 0x00000001b3c4aa90 -[UINavigationTransitionView _cleanupTransition] + 584
19 UIKitCore 0x00000001b3c58950 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 308
20 UIKitCore 0x00000001b3c5438c +[UIViewAnimationState popAnimationState] + 332
21 UIKitCore 0x00000001b3c4a518 -[UINavigationTransitionView transition:fromView:toView:] + 1860
22 UIKitCore 0x00000001b318cb1c -[UINavigationController _startTransition:fromViewController:toViewController:] + 2652
23 UIKitCore 0x00000001b318d0f8 -[UINavigationController _startDeferredTransitionIfNeeded:] + 1180
24 UIKitCore 0x00000001b318e3f8 -[UINavigationController __viewWillLayoutSubviews] + 160
25 UIKitCore 0x00000001b31705e8 -[UILayoutContainerView layoutSubviews] + 220
26 UIKitCore 0x00000001b3c8f7dc -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1376
27 QuartzCore 0x000000018ac4db74 -[CALayer layoutSublayers] + 180
28 QuartzCore 0x000000018ac52b2c CA::Layer::layout_if_needed(CA::Transaction*) + 320
29 QuartzCore 0x000000018abb144c CA::Context::commit_transaction(CA::Transaction*) + 336
30 QuartzCore 0x000000018abdfd7c CA::Transaction::commit() + 604
31 UIKitCore 0x00000001b380fa3c _afterCACommitHandler + 252
32 CoreFoundation 0x00000001865e07cc __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 28
33 CoreFoundation 0x00000001865db460 __CFRunLoopDoObservers + 408
34 CoreFoundation 0x00000001865dba00 __CFRunLoopRun + 1260
35 CoreFoundation 0x00000001865db1f0 CFRunLoopRunSpecific + 432
36 GraphicsServices 0x0000000188854584 GSEventRunModal + 96
37 UIKitCore 0x00000001b37e6d40 UIApplicationMain + 208
38 XXXApp 0x00000001006c96e4 main (main.m:16)
39 libdyld.dylib 0x000000018609abb4 start + 0
答案 2 :(得分:-1)
exports.getTest = (req, res, next) => {
var categories = [];
var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
names.forEach(name => {
Category.findOne({where: {name: name}}).then(category => {
categories.push({category_id: category.id})
})
})
res.json(categories);
}
因此,基本上,model.findeOne()返回带有第一个类别的对象以及每个名称的Promise。 then()捕获了那个诺言,将其解析,然后给它一个回调函数,该回调函数将该对象作为参数传递。
可能看起来像
Categories.findOne({where: {name: name}).then(function(category){
// do something with that category
})
但是arrow函数使它比那时更具可读性(category => {// some 代码}。