在遇到返回之前,当执行到达块的末端时,解析承诺会发生什么情况?

时间:2022-11-22 20:58:13

Suppose I have the following Parse cloud code:

假设我有以下解析云代码:

// assume myObj is a parse object
myObj.set("field1", "foo");
Parse.Promise.as().then(function() 
  myObj.save(myObj, {
    success: function(savedObj) {
      // A
      return Parse.Promise.as();
    },
    error: function(myObj, error) {
      // B
      return Parse.Promise.as();
    }
  });
  // C
  // note that we can get here without any return statement being called
}).then(function() {
  // D
});

(Now, i know it would be simpler to just use promises for the whole thing:

(现在,我知道对整个事情使用承诺会更简单:

myObj.save().then(
  ...

...but there are some functions that don't return promises, so sometimes you have no choice but to mix Backbone-style success/error blocks with promises.)

…但是有一些函数不返回承诺,所以有时您别无选择,只能将backbone风格的成功/错误块与承诺混合在一起。

My question:

我的问题:

What happens when C is reached? Does execution pause on this promise until one of those return statements is reached, and then execution reaches D? Does execution advance directly to D after reaching C, without waiting for a return statement? Is this an error?

达到C时会发生什么?执行是否暂停此承诺,直到到达其中一个返回语句,然后执行到达D?执行是否在到达C后直接推进到D,而不等待返回语句?这是一个错误吗?

In other words, is it possible for execution to happen in the order C, D, A/B? Or will it always be C, A/B, D? (Or, I suppose, if save finishes crazy fast, something like A/B, C, D?)

换句话说,是否有可能按照C、D、A/B的顺序执行?还是总是C A/B D?(或者,我想,如果save很快完成,比如A/B、C、D?)

3 个解决方案

#1


3  

Your returns are from the inner functions. If it was up to me I'd promisify the save function itself. However, if you're convinced you don't want to do this you still have to return a Parse.Promise from the then if you want it to wait for anything.

你的回报来自内部函数。如果由我来决定,我就会宣传save函数本身。但是,如果您确信不想这样做,那么仍然需要返回一个解析。从那时起,如果你想让它等待任何事情。

The then function returns a new promise and resolves that promise (executes further thens) when its return value is resolved. If that's just a value it will not wait for anything - if it's a promise it will wait for it in turn to resolve.

then函数返回一个新的承诺,并在其返回值被解析时解析该承诺(进一步执行thens)。如果这只是一个价值,它不会等待任何东西——如果这是一个承诺,它会等待它的解决。

Please look at how to promisify for further reading.

请参阅如何作进一步阅读。

In your example - this would look something like:

在你的例子中,这看起来像是:

myObj.set("field1", "foo");
Parse.Promise.as().then(function(){
  var p = Parse.Promise();
  myObj.save(myObj, {
    success: p.resolve.bind(p), // on success, resolve the promise
    error: p.reject.bind(p) // on failure, reject it
  });
  // any code here _will_ execute before the `then` is called.
  return p; // return the promise so `then` will wait
}).then(function(savedObj) {
    // this will always run after `myObj.save` completed
    // you can add a catch handler for the error case
});

However, if we pay attention we can notice Parse's save method already returns a promise - Parse promisified it for us - so this code can be significantly reduced to:

但是,如果我们注意,我们可以注意到Parse的save方法已经返回了一个承诺——Parse将其推广给我们——因此这段代码可以显著地简化为:

myObj.set("field1", "foo");
Parse.Promise.as().then(function(){

  return myObj.save(myObj)
}).then(function(savedObj) {
  // this will always run after `myObj.save` completed
  // you can add a catch handler for the error case
});

Which in turn can be reduced to:

反过来又可归纳为:

myObj.set("field1", "foo");
myObj.save().then(function(savedObj){
   // object save is done here
});   

#2


0  

Answer seems to be that it won't wait for A or B -- it'll move on, probably with D executing before A or B.

答案似乎是它不会等待A或B——它会继续前进,可能D在A或B之前执行。

In any case, it's basically a bug -- though not one the runtime will complain about -- to invoke asynchronous code (like I do with save()) but not explicitly return a local promise at the end of a then function block that would make the bigger promise wait until the asynchronous code finishes. In other words, I should do something like Benjamin Gruenbaum's answer suggests.

在任何情况下,它基本上是一个错误——尽管不是一个运行时将抱怨——调用异步代码与保存()(像我一样),但没有明确返回一个本地承诺的功能块,将使更大的承诺等待异步代码完成。换句话说,我应该像本杰明·格伦鲍姆(Benjamin Gruenbaum)的回答那样做。

#3


0  

As a rule of thumb just keep returning promises, they will be automagically resolved. All Parse async methods return promises so just keep returning until you are done. I wouldn't recommend to use the success and error methods. Using callbacks and promises together is not a good idea since you have to write a lot of extra code to account for it. If everything in your app return promises you can remove a block or add a another one very easily. Just create functions that return a promise.

根据经验,只要不断地返回承诺,它们就会自动解决。所有的Parse async方法都返回承诺,所以直到你完成。我不建议使用成功和错误方法。同时使用回调和承诺不是一个好主意,因为您必须编写大量额外的代码来说明这一点。如果你的应用程序中所有的东西都有承诺,你可以删除一个块,或者很容易地添加另一个块。只需创建返回承诺的函数。

Also, how you return promises while vary depending on the scope needed in each block.

此外,您如何返回承诺,同时根据每个块所需的范围有所不同。

So for example:

举个例子:

function myPromise (a) {
  return Parse.Promise.as({name: 'David Bowie', a : a});
}

myObj.set("a", 1);

myObj.save(obj).then(function(obj) {
  var a = obj.get('a');
  return Parse.Promise.as()
    .then(function() {
      return Parse.Object.saveAll([])
        .then(function() {
          a += 1
          return Parse.Promise.as(a);
      })
    })
}).then(function(a){
  return myPromise(a);
})
.then(function(davidBowie) {
  console.log(davidBowie.name);
  console.log(davidBowie.a);
})
.fail(function() {
  // handle error
})

#1


3  

Your returns are from the inner functions. If it was up to me I'd promisify the save function itself. However, if you're convinced you don't want to do this you still have to return a Parse.Promise from the then if you want it to wait for anything.

你的回报来自内部函数。如果由我来决定,我就会宣传save函数本身。但是,如果您确信不想这样做,那么仍然需要返回一个解析。从那时起,如果你想让它等待任何事情。

The then function returns a new promise and resolves that promise (executes further thens) when its return value is resolved. If that's just a value it will not wait for anything - if it's a promise it will wait for it in turn to resolve.

then函数返回一个新的承诺,并在其返回值被解析时解析该承诺(进一步执行thens)。如果这只是一个价值,它不会等待任何东西——如果这是一个承诺,它会等待它的解决。

Please look at how to promisify for further reading.

请参阅如何作进一步阅读。

In your example - this would look something like:

在你的例子中,这看起来像是:

myObj.set("field1", "foo");
Parse.Promise.as().then(function(){
  var p = Parse.Promise();
  myObj.save(myObj, {
    success: p.resolve.bind(p), // on success, resolve the promise
    error: p.reject.bind(p) // on failure, reject it
  });
  // any code here _will_ execute before the `then` is called.
  return p; // return the promise so `then` will wait
}).then(function(savedObj) {
    // this will always run after `myObj.save` completed
    // you can add a catch handler for the error case
});

However, if we pay attention we can notice Parse's save method already returns a promise - Parse promisified it for us - so this code can be significantly reduced to:

但是,如果我们注意,我们可以注意到Parse的save方法已经返回了一个承诺——Parse将其推广给我们——因此这段代码可以显著地简化为:

myObj.set("field1", "foo");
Parse.Promise.as().then(function(){

  return myObj.save(myObj)
}).then(function(savedObj) {
  // this will always run after `myObj.save` completed
  // you can add a catch handler for the error case
});

Which in turn can be reduced to:

反过来又可归纳为:

myObj.set("field1", "foo");
myObj.save().then(function(savedObj){
   // object save is done here
});   

#2


0  

Answer seems to be that it won't wait for A or B -- it'll move on, probably with D executing before A or B.

答案似乎是它不会等待A或B——它会继续前进,可能D在A或B之前执行。

In any case, it's basically a bug -- though not one the runtime will complain about -- to invoke asynchronous code (like I do with save()) but not explicitly return a local promise at the end of a then function block that would make the bigger promise wait until the asynchronous code finishes. In other words, I should do something like Benjamin Gruenbaum's answer suggests.

在任何情况下,它基本上是一个错误——尽管不是一个运行时将抱怨——调用异步代码与保存()(像我一样),但没有明确返回一个本地承诺的功能块,将使更大的承诺等待异步代码完成。换句话说,我应该像本杰明·格伦鲍姆(Benjamin Gruenbaum)的回答那样做。

#3


0  

As a rule of thumb just keep returning promises, they will be automagically resolved. All Parse async methods return promises so just keep returning until you are done. I wouldn't recommend to use the success and error methods. Using callbacks and promises together is not a good idea since you have to write a lot of extra code to account for it. If everything in your app return promises you can remove a block or add a another one very easily. Just create functions that return a promise.

根据经验,只要不断地返回承诺,它们就会自动解决。所有的Parse async方法都返回承诺,所以直到你完成。我不建议使用成功和错误方法。同时使用回调和承诺不是一个好主意,因为您必须编写大量额外的代码来说明这一点。如果你的应用程序中所有的东西都有承诺,你可以删除一个块,或者很容易地添加另一个块。只需创建返回承诺的函数。

Also, how you return promises while vary depending on the scope needed in each block.

此外,您如何返回承诺,同时根据每个块所需的范围有所不同。

So for example:

举个例子:

function myPromise (a) {
  return Parse.Promise.as({name: 'David Bowie', a : a});
}

myObj.set("a", 1);

myObj.save(obj).then(function(obj) {
  var a = obj.get('a');
  return Parse.Promise.as()
    .then(function() {
      return Parse.Object.saveAll([])
        .then(function() {
          a += 1
          return Parse.Promise.as(a);
      })
    })
}).then(function(a){
  return myPromise(a);
})
.then(function(davidBowie) {
  console.log(davidBowie.name);
  console.log(davidBowie.a);
})
.fail(function() {
  // handle error
})