简体   繁体   English

Angularjs使用promise在另一个之后加载资源

[英]Angularjs load resources on after the other using promise

Inside a service, I would like to load a resource using $http. 在服务中,我想使用$ http加载资源。 Once loaded resource, I want to store it in a variable. 加载资源后,我想将其存储在变量中。 Then, I need to load a child resource and store it too. 然后,我需要加载子资源并存储它。 I know that the promise is designed for this kind of work, but there seems to be so much how to use it I get a little confusion. 我知道这个承诺是为这种工作而设计的,但似乎有很多如何使用它我有点混乱。 Here is my code: 这是我的代码:

var project = {};
var todo = {};

function init(){
        var idProject = 21;
        var idTodo = 6;            

        // If idProject is specified
        if ( idProject != null ) {

            // First, load project data
            var promise = WorkspaceManager.getProject($rootScope.workspace, idProject);

            // Then save project data
            promise.then(function(response){
                project = response.data;                    
                return project;
            });

            if ( idTodo != null ) {
                //  Then load todo data
                promise.then(function(project){   
                    return ProjectManager.getTodo(project, idTodo);
                });

                // Then save todo data
                promise.then(function(response){
                    todo = response.data;                    
                    return todo;
                });
            }       
        }

        console.log(project); // returns {}
    }

init()

Thanks in advance ! 提前致谢 !

The way you doing, you're creating "brothers" promise derived from the first promise. 你做的方式,你正在创造源自第一个承诺的“兄弟”承诺。 All the promises are going to be resolved as soon as WorkspaceManager.getProject promise has been resolved. 一旦解决了WorkspaceManager.getProject承诺,所有承诺将立即得到解决。 What I believe you want is to chain them all, in way that when first promise gets resolved, yo asks for Todo data, when you got it, you asks to save it. 我相信你想要的是将它们全部链接起来,当第一个承诺得到解决时,你要求Todo数据,当你得到它时,你要求保存它。 If this is the case, you shall grab the derived promise from each promise. 如果是这种情况,您应该从每个承诺中获取派生的承诺。

// Then save project data
promise = promise.then(function(response){
  project = response.data;
  return project;
});

//  Then load todo data
promise = promise.then(function(project){   
  return ProjectManager.getTodo(project, idTodo);
});

// Then save todo data
promise.then(function(response){
  todo = response.data;                    
  return todo;
});

Trying to illustrate a bit more, the first approach is like: 试图说明一点,第一种方法是:

var mainPromise = ...;
mainPromise.then(function loadTodo(mainPromiseReturn){});
mainPromise.then(function saveTodo(mainPromiseReturn){});

The loadTodo and saveTodo are pararell, they're not chained to each other. loadTodosaveTodo是pararell,它们没有相互链接。 They both receive the same data . 他们都收到相同的data

The approach I suggest is like: 我建议的方法是:

var mainPromise = ...;
mainPromise
  .then(function loadTodo(mainPromiseReturn){})
  .then(function saveTodo(loadTodoReturn){});

If I understand correctly, this is trickier than it appears at first glance. 如果我理解正确,这比乍看之下更难。 You appear to need a function that chains two asynchronous processes and returns a promise of a composite value comprising data acquired by the first and the second processes. 您似乎需要一个链接两个异步进程的函数,并返回包含第一个第二个进程获取的数据的复合值的承诺。

At least two approaches are available : 至少有两种方法可供选择:

  • Easy but inelegant : In each asynchronous process, accumulate the required values as properties of an outer object. 简单但不优雅 :在每个异步过程中,将所需的值累积为外部对象的属性。
  • Elegant but awkward : From each asynchronous process, accumulate the required values as properties of an object, a promise of which is returned. 优雅但尴尬 :从每个异步过程中,将所需的值累积为对象的属性,返回其承诺。

The code below adopts the first approach : 以下代码采用第一种方法:

function init() {
    var idProject = 21;
    var idTodo = 6;
    var projectObj = {};//This object acts as a "bank" for asynchrounously acquired data.
    if ( idProject != null ) {
        return WorkspaceManager.getProject($rootScope.workspace, idProject).then(function(response) {
            projectObj.project = response.data;//put `response.data` in the bank as .project.
            if( idTodo != null ) {
                return ProjectManager.getTodo(response.data, idTodo);
            }
        }).then(function(toDo) {
            projectObj.toDo = toDo;//put `toDo` in the bank as .toDo .
            return projectObj;
        });
    }
}

init().then(function(projectObj) {
    console.log(projectObj.project);
    console.log(projectObj.toDo);
});

Or (still the first approach) with error handlers : 或者(仍然是第一种方法)使用错误处理程序:

function init() {
    var idProject = 21;
    var idTodo = 6;
    var projectObj = {};//This object acts as a "bank" for asynchrounously acquired data.
    if ( idProject != null ) {
        return WorkspaceManager.getProject($rootScope.workspace, idProject).then(function(response) {
            projectObj.project = response.data;//put `response.data` in the bank as .project.
            if( idTodo != null ) {
                return ProjectManager.getTodo(response.data, idTodo);
            }
            else {
                $q.defer().reject('idTodo invalid');
            }
        }).then(function(toDo) {
            projectObj.toDo = toDo;//put `toDo` in the bank as .toDo .
            return projectObj;
        });
    }
    else {
        return $q.defer().reject('idProject invalid');
    }
}

init().then(function(projectObj) {
    console.log(projectObj.project);
    console.log(projectObj.toDo);
}, function(errorMessage) {
    console.log(errorMessage);
});

untested 未经测试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM