Javascript承诺结果范围

时间:2014-02-09 18:11:56

标签: javascript promise

我需要链接一些异步行为。我正在尝试编写使用express的Parse.com云代码。 (我认为快递是承诺支持的起源)。我明白为什么承诺是有价值的,但我仍然不确定几件事情。第一个是如何收集有序行动的结果。下面的代码说明了:

function doAsnychThingsInSequence(params) {
  return doThing0(params).then(function(resultOfThing0) {
    // thing1 depends on resultOfThing0
    doThing1(resultOfThing0);
  }).then(function(resultOfThing1) {
    // here is where I am confused.
    // thing2 depends on the results of thing0 and thing1
    doThing2(resultOfThing0 /* out of scope?? */, resultOfThing1);
  }, function(error) {
    // handle error
  });
}

在完成thing1之后,我需要两个动作的结果。我想我可以在函数顶部分配一个变量并将其分配给第一个回调中的第一个结果,这是正确的方法吗?我想,我困惑的核心是问题二......

  return doThing0(params0).then(function(resultOfThing0) {
    doThing1(resultOfThing0);
    // what does return mean here?  does what I return here relate to the
    // parameters of the next function?
    return "foo";
  }).then(function(param) {
    // what is in param?  is it "foo"?
  }, function(error) {
});

3 个答案:

答案 0 :(得分:1)

Promise可以被想象为流处理:一个函数获取输入,对其执行某些操作并将其传递给链中的下一个函数。

因此,如果您需要进一步传递输入(对于链)参数,则应将它们包括在内 输出数据,以便链中的下一个可以使用它们:

function doThing1(params1) {
  ...
  return [params1, result1];
}

function doThing2(params1, params2) {
  ...
}

正如您所提到的,您可以在doThing1和doThing2之外使用一些变量,但它会使这些函数状态良好,可能会导致各种副作用。通常不希望异步处理。

答案 1 :(得分:1)

提供给then()的函数必须返回一个值,无论该值是要使用的值,还是对即将到来的值的承诺。无论哪种方式(根据承诺规范)then()都会返回新的承诺。这是我在你的代码中看到的第一个问题。

接下来,您必须将thing1存储在更高的范围内,以便以后可以访问它。所以这样的事情可能是有序的:

// example
var thing1;
getThing1()
.then(function(value){
  thing1 = value; // <-- store in higher scope
  return getThing2(); // <-- return
})
.then(function(value){
  thing2 = value;
  // now you have both thing1 and thing2 in scope
})

答案 2 :(得分:1)

我想总结一下我从@greim和@ c-smile的两个有用答案中学到的东西。 +1都是善意的帮助。但如果我理解正确,那么对于Promises来说这是令我失望的。

@ greim的回答将使我的回调引用包含函数中的局部变量。但这是令人失望的,因为它使回调依赖于那些本地人。例如,传递回调很难。

@ c-smile的回答将使我的函数返回其参数及其结果的数组(或某些集合)。然后,期望该函数的所有调用者挖掘“自然”结果的返回值,而不是它用于获得结果的参数。

根据我原来的帖子重述答案:

// @greim

function doAsnychThingsInSequence(params) {
  var theResultOfThing0;  // yuck, for needing to make up a non-colliding variable name
  return doThing0(params).then(function(resultOfThing0) {
    theResultOfThing0 = resultOfThing0; 
    return doThing1(resultOfThing0);
  }).then(function(resultOfThing1) {
    return doThing2(theResultOfThing0, resultOfThing1);
  }, function(error) {
    // handle error
  });
}

// @c-smile

function doThing1(params) {  // params are resultOfThing0
  // do stuff
  // the "natural" answer is just resultOfThing1, but ...
  return [params, resultOfThing1];
}

// if this function was doThingN, then we'd have
  return [params0, params1 ... paramsN, resultOfThingN];  // yikes!

// at least this method looks great now, how I want it to look...
function doAsnychThingsInSequence(params) {
  return doThing0(params).then(function(resultOfThing0) {
    return doThing1(resultOfThing0);
  }).then(function(resultOfThing0, resultOfThing1) {
    return doThing2(resultOfThing0, resultOfThing1);
  }, function(error) {
    // handle error
  });
}