1

次の Parse クラウド コードがあるとします。

// 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
});

(今、私はすべてのために約束を使用する方が簡単であることを知っています:

myObj.save().then(
  ...

...しかし、Promise を返さない関数がいくつかあるため、Backbone スタイルの成功/エラー ブロックを Promise と混在させるしかない場合があります。)

私の質問:

Cに達するとどうなりますか?これらの return ステートメントの 1 つに到達するまで、この promise で実行が一時停止し、その後 D に到達しますか? C に到達した後、return 文を待たずに直接 D に実行が進みますか? これはエラーですか?

言い換えれば、C、D、A/B の順序で実行することは可能でしょうか? それとも、常に C、A/B、D になりますか? (または、保存が非常に速く終了する場合、A/B、C、D のようなものだと思いますか?)

4

3 に答える 3

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.

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.

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:

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
});   
于 2014-09-12T17:41:51.120 に答える
0

答えは、A または B を待たないということのようです。おそらく、A または B の前に D が実行されて、先に進みます。

いずれにせよ、(save() で行うように) 非同期コードを呼び出すが、then 関数ブロックの最後にローカルの promise を明示的に返さないことは、基本的にバグです (ランタイムが文句を言うことはありません)。非同期コードが終了するまで、より大きな約束を待ちます。つまり、Benjamin Gruenbaum の回答が示唆するようなことを行う必要があります。

于 2014-09-12T19:28:25.940 に答える
0

経験則として、約束を返し続けるだけで、自動的に解決されます。すべての Parse 非同期メソッドは promise を返すため、完了するまで戻り続けます。successanderrorメソッドの使用はお勧めしません。コールバックとプロミスを一緒に使用することは、それを説明するために多くの余分なコードを記述する必要があるため、良い考えではありません。アプリ内のすべてが promise を返す場合、ブロックを削除したり、別のブロックを追加したりするのは非常に簡単です。promise を返す関数を作成するだけです。

また、promise を返す方法は、各ブロックで必要なスコープによって異なります。

たとえば、次のようになります。

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
})
于 2014-09-12T20:16:25.783 に答える