Parse.Cloud.job 承诺无效

Parse.Cloud.job promise not working

我在这里要做的是:

  1. 先删除class中的所有内容,因为events.json文件每天都会更新。我在这里有第一个问题:是否有更好的方法从 Parse class 数据库中删除所有内容?

  2. 然后我会发送请求获取events.json并将结果的"name"和"id"存储到一个二维数组中。

  3. 然后我将发送多个请求以获取每个 "name" 和 "id" 对的 json 个文件。

  4. 最后,我会将事件的详细信息存储到数据库中。 (每行一个事件)但是现在我的代码将在下载 json 文件之前终止。

代码:

function newLst(results) {
  var event = Parse.Object.extend("event");
  for (var i = 0; i < results.length; i++){
    Parse.Cloud.httpRequest({
      url: 'https://api.example.com/events/'+ results[i].name +'/'+ results[i].id +'.json',
      success: function(newLst) {
        var newJson = JSON.parse(newLst.text);
        var newEvent = new event();
        newEvent.set("eventId",newJson.data.id);
        newEvent.set("eventName",newJson.data.title);
        newEvent.save(null, {
          success: function(newEvent) {
            alert('New object created with objectId: ' + newEvent.id);
          },
          error: function(newEvent, error) {
            alert('Failed to create new object, with error code: ' + error.message);
          }
        });
      },
      error: function(newLst) {
      }
    });
  }
};

Parse.Cloud.job("getevent", function(request, status) {
  var event = Parse.Object.extend("event");
  var query = new Parse.Query(event);
  query.notEqualTo("objectId", "lol");
  query.limit(1000);
  query.find({
    success: function(results) {
      for (var i = 0; i < results.length; i++) { 
        var myObject = results[i];
        myObject.destroy({
          success: function(myObject) {
          },
          error: function(myObject, error) {
          }
        });
      }
    },
    error: function(error) {
      alert("Error: " + error.code + " " + error.message);
    }
  });
  var params = { url: 'https://api.example.com/events.json'};
  Parse.Cloud.httpRequest(params).then(function(httpResponse) {
      var results = [];
      var jsonobj = JSON.parse(httpResponse.text);
      for (var i = 0; i < jsonobj.data.length; i++) {
        var tmp2D = {"name":"id"}
        tmp2D.name = [jsonobj.data[i].name];
        tmp2D.id = [jsonobj.data[i].id];
        results.push(tmp2D);
      }
      newLst(results);
  }).then(function() {
      status.success("run job");
  }, function(error) {
      status.error(error);
  });
});

posted 代码只执行一个 http 请求,因此不需要一组承诺或调用 Promise.when()。通过将 httpRequest 的回调参数与 promises 和推送中的分配混合在一起,可能会发生的其他事情变得模糊不清。

这里是一个明确的重写:

Parse.Cloud.job("getevent", function(request, status) {
    var promises = [];
    var params = { url: 'https://api.example.com'};
    Parse.Cloud.httpRequest(params).then(function(httpResponse) {
        var results = [];
        var jsonobj = JSON.parse(httpResponse.text);
        for (var i = 0; i < jsonobj.data.length; i++) {
            // some code
        }
    }).then(function() {
        status.success("run job");
    }, function(error) {
        status.error(error);
    });
});

但这里有一个非常强烈的警告:仅当出现在原始 post 中的(“// 一些代码”)本身不尝试执行任何异步工作、数据库或其他方式时,这才有效。

假设您确实需要在该循环中执行异步工作。将该工作移至承诺返回函数,将这些函数收集到数组中,然后然后 使用Promise.when()。例如....

// return a promise to look up some object, change it and save it...
function findChangeSave(someJSON) {
    var query = new Parse.Query("SomeClass");
    query.equalTo("someAttribute", someJSON.lookupAttribute);
    return query.first().then(function(object) {
        object.set("someOtherAttribute", someJSON.otherAttribute);
        return object.save();
    });
}

然后,在你的循环中...

        var jsonobj = JSON.parse(httpResponse.text);
        var promises = [];
        for (var i = 0; i < jsonobj.data.length; i++) {
            // some code, which is really:
            var someJSON = jsonobj.data[i];
            promises.push(findChangeSave(someJSON));
        }
        return Parse.Promise.when(promises);

我认为我的原始答案作为一个独立的答案是正确的。与其用额外的代码让它变得不可读,不如让它变得非常适合您的编辑。

关键是消除传递的回调函数。下面的一切都使用承诺。另一个关键想法是将活动分解成逻辑块。

一些注意事项:(1) 那里有很多代码,您的代码错误或我的代码错误的可能性仍然很高,但这应该传达更好设计的要点。 (2) 我们在这些函数中做了足够的工作,我们可能会遇到解析强加的超时。首先用小计数测试所有这些。

从你关于销毁 class...

的所有实例的问题开始
// return a promise to destroy all instances of the "event" class
function destroyEvents() {
    // is your event class really named with lowercase?  uppercase is conventional
    var query = new Parse.Query("event");
    query.notEqualTo("objectId", "lol");  // doing this because the OP code did it.  not sure why
    query.limit(1000);
    return query.find().then(function(results) {
        return Parse.Object.destroyAll(results);
    });
}

接下来,获取远程事件并将其格式化为简单 JSON。看到评论。我很确定你关于“二维数组”的想法是不明智的,但我可能误解了你的数据...

// return a promise to fetch remote events and format them as an array of objects
//
// note - this differs from the OP data.  this will evaluate to:
// [ { "name":"someName0", id:"someId0" }, { "name":"someName1", id:"someId1" }, ...]
//
// original code was producing:
// [ { "name":["someName0"], id:["someId0"] }, { "name":["someName1"], id:["someId1"] }, ...]
// 
function fetchRemoteEvents() {
    var params = { url: 'https://api.example.com/events.json'};
    return Parse.Cloud.httpRequest(params).then(function(httpResponse) {
        var results = [];
        var remoteEvents = JSON.parse(httpResponse.text).data;
        for (var i = 0; i < remoteEvents.length; i++) {
            var remoteEvent = { "name": remoteEvents[i].name, "id": remoteEvents[i].id };
            results.push(remoteEvent);
        }
        return results;
    });
}

请仔细检查我上面关于格式的所有工作(例如 response.text、JSON.parse().data 等)。

当你混合回调和承诺时很容易混淆,当你在循环中生成承诺时更糟。在这里,我们再次提出一个简单的操作,根据我们在上面的函数中获得的单个远程事件之一创建一个 parse.com 对象...

// return a promise to create a new native event based on a remoteEvent
function nativeEventFromRemoteEvent(remoteEvent) {
    var url = 'https://api.example.com/events/'+ remoteEvent.name +'/'+ remoteEvent.id +'.json';
    return Parse.Cloud.httpRequest({ url:url }).then(function(response) {
        var eventDetail = JSON.parse(response.text).data;
        var Event = Parse.Object.extend("event");
        var event = new Event();
        event.set("eventId", eventDetail.id);
        event.set("eventName", eventDetail.title);
        return event.save();
    });
}

最后,我们可以将它放在一个简单易读的作业中,确定按所需顺序做事,并且确定在(且仅当)它成功完成时调用 success()...

// the parse job removes all events, fetches remote data that describe events
// then builds events from those descriptions
Parse.Cloud.job("getevent", function(request, status) {
    destroyEvents().then(function() {
        return fetchRemoteEvents();
    }).then(function(remoteEvents) {
        var newEventPromises = [];
        for (var i = 0; i < remoteEvents.length; i++) {
            var remoteEvent = remoteEvents[i];
            newEventPromises.push(nativeEventFromRemoteEvent(remoteEvent));
        }
        return Parse.Promise.when(newEventPromises);
    }).then(function() {
        status.success("run job");
    }, function(error) {
        status.error(error);
    });
});