【问题标题】:Breaking the callback chain - Node [duplicate]打破回调链 - 节点 [重复]
【发布时间】:2017-12-07 08:26:11
【问题描述】:

我想知道是否可以将回调的值分配给变量。我最近遇到了 MongoClient 的 connect 方法的问题,我想在其中获取 db 对象并将其传递给我的类方法。有没有办法我可以将hello world 分配给var b

function testCB(cb){
  setTimeout(() => {
    cb('Hello World')
  }, 1000)
}

let b = testCB('a', (str) => {
  return str;
})

console.log(b) //undefined

【问题讨论】:

  • 使用异步方法(setTimeout 是异步的)意味着您必须编写代码来处理异步性......没有什么可以将异步代码更改为同步 - 顺便说一句,testCB 函数甚至没有有一个 return 语句,所以它永远不会返回任何东西
  • 您可以将b = str; 放在回调中,但console.log(b) 仍会显示undefined,因为它在回调运行之前运行。想一想:如果您能以某种方式将回调中的值神奇地分配给b同步,那么为什么首先需要回调?

标签: javascript node.js express ecmascript-6 asynccallback


【解决方案1】:

目前,您将调用testCB 的结果分配给b,但testCB 没有返回任何内容,因此没有分配给b

但是这种模式并没有错:

var b;

testCB( (str) => { b = str; } );

这是在变量 (b) 中维护应用程序状态并使用异步函数修改该状态的最简单版本。

如果您的应用程序的许多部分依赖于b,并且您希望同步定义该依赖关系:这就是Promises 的用途!

在这种情况下,您可以定义:

var b = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Hello World'), 1000);
});

b.then((str) => {...do something with str...}
b.then((str) => {...do something else with str...}
doSomeThingWithB(b);

doSomeThingWithB 当然知道b 是一个承诺(或“thennable”)。

【讨论】:

  • "这个模式没有错" - 当然有:所有使用b的代码都不知道它是否已经被赋值.
  • @Bergi 但是,当您异步修改状态变量时,情况总是如此。 b 中的“订阅更改”和处理 undefined 状态的问题是另一个问题,而不是 OP 所要求的。问题是如何“突破”回调范围。
  • 我很确定他的意思是“突破回调范围”,同时仍然做同样的事情。不能将console.log 放在回调之外,或者至少是一个单独的范围。
【解决方案2】:

由于事件是异步的,您需要遵循异步代码流程。所以“获得回报”的唯一方法是在你的回调函数中,即:

function testCB(cb){
  setTimeout(() => {
    cb('Hello World')
  }, 1000)
}

let b = testCB('a', (str) => {
  // this executes async, when testCB finishes running
  console.log(str) // will print STR
  return str;
})
// this code executes BEFORE testCB finish running,
// so it is imposible to get the value of str here.

如果您想要更流畅的代码,可以尝试使用带有asyncawait 的promise,它们在节点7+ 上可用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    • 2018-12-22
    • 2020-06-12
    • 1970-01-01
    • 2016-04-03
    • 1970-01-01
    • 2013-12-14
    相关资源
    最近更新 更多