将then的值保存在Promise之外的变量中

时间:2019-05-28 17:51:13

标签: javascript node.js express promise sequelize.js

我对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:我知道这是一个常见的话题,但是正如我提到的,我对此很陌生,其他答案与我的情况不符,进一步使我感到困惑。

谢谢!

3 个答案:

答案 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 代码}。