2015-07-01 2 views
1

Как правильно использовать отсрочку? У меня есть две функции здесь, в которых один отсрочка используется правильно? В каком из них он используется неправильно? И почему. почему нет?Как использовать defer() правильный путь?

Первый пример:

getFoo1: function() { 
    var dfd = $q.defer(); 

    db.allDocs({include_docs: true}, function(err, response) { 
    if(err) { 
     console.log(err); 
     dfd.reject(err); 
    } else { 
     var qcs = []; 
     for(var i=0; i < response.total_rows; i++) { 
     if(response.rows[i].doc.type == 'bar') { 

      var qc = {id: response.rows[i].doc._id, 
      isFoo: true 
      }; 

      oneFunction(qc) 
      .then(anotherFunction(qc)) 
      .then(qcs.push(qc)); 
     } 
     } 
     dfd.resolve(qcs); 
    } 
    }); 
    return dfd.promise; 
}, 

Второй пример:

getFoo2: function() { 
    var dfd = $q.defer(); 

    db.allDocs({include_docs: true}, function(err, response) { 
    if(err) { 
     dfd.reject(err); 
    } else { 
     dfd.resolve(response); 
    } 
    }); 

    return dfd.promise 
    .then(function(response) { 
    var foo = []; 
    for(var i=0; i < response.total_rows; i++) { 
     if(response.rows[i].doc.type == 'bar') { 
     var qc = {id: response.rows[i].doc._id, 
      isFoo: true 
     }; 

     return oneFunction(qc) 
     .then(anotherFunction(qc)) 
     .then(foo.push(qc)); 
     } 
    } 
    }, function(err){ 
    console.log(err); 
    }); 
}, 

oneFunction ничего не делает асинхронно.

anotherFunction делает что-то асинхронно (получение данных из внешней базы данных).

EDIT: Благодаря @Bergi правильной функции должен выглядеть следующим образом:

getFoo3: function() { 
    var dfd = $q.defer(); 

    db.allDocs({include_docs: true}, function(err, response) { 
    if(err) { 
     dfd.reject(err); 
    } else { 
     dfd.resolve(response); 
    } 
    }); 

    return dfd.promise 
    .then(function(response) { 
    var foos = []; 

    for (var i=0; i < response.total_rows; i++) { 
    if (response.rows[i].doc.type == 'bar') { 
     var qc = {id: response.rows[i].doc._id, 
     isFoo: true 
     }; 
     var foo = oneFunction(qc); 
     foos.push(foo); 
    } 
    } 

    var promises = foos.map(anotherFunction); // make a promise for each foo 
    return $q.all(promises); 

    }, function(err){ 
    console.log(err); 
    }); 
}, 
+0

в 'затем' вы должны передать ссылку на функцию, но вместо того, чтобы вам мгновенный вызов функции, как' anotherFunction (дс) '. Так кажется, что в обоих он неправильно использовался :-) – Grundy

+0

Не могли бы вы рассказать о своем комментарии, пожалуйста? В какой части? Как должна выглядеть функция, @Grundy? – thadeuszlay

+0

если вы объясните, что вы ожидали, я могу попробовать объяснить, как это должно быть. В любом случае я имею в виду '.то (anotherFunction (qc)) 'должно быть как' .then (function() {anotherFunction (qc)}) 'до тех пор, пока функция' otherFunction' не будет возвращена – Grundy

ответ

2

Вы использовали $q.defer правильно во втором примере [1] - создание перспективы для ответа на db.allDocs асинхронный вызов (и ничего больше). Похоже, что pochdb, похоже, уже возвращает обещания, так как @Benjamin упоминает в комментариях, поэтому он не нужен (но не ошибается).

Первый пример - это просто беспорядок, свернувший конструкцию обещания с регистрацией ошибок и этим зловещим циклом.

1: За исключением dfd.promise(), который не является функцией, а является собственностью. Перейдите на dfd.promise.then(…).

Однако этот цикл является совсем другой темой и, по-видимому, является неправильным в обоих фрагментах. Некоторые моменты:

  • Во втором фрагменте, ваш return от функции обратного вызова в теле цикла, прямо на первой итерации, который удовлетворяет предикату.
  • Если oneFunction(qc) не является асинхронным, ему не нужно (читать: не следует) возвращать обещание - или если это не так, то вызов .then(…) неверен.
  • anotherFunction(qc), кажется, возвращает обещание (это асинхронно, как вы говорите). Но вы не должны передавать это обещание .then(), здесь ожидается функция обратного вызова!
  • То же самое для foo.push(qc) - это не функция обратного вызова, которую вы передали бы .then().
  • В конце концов, вы делаете что-то асинхронное в этом цикле. Здесь you have to usePromise.all сейчас!

Если бы мне пришлось держать пари, я бы сказал, что вам нужно

.then(function(response) { 
    var foos = []; 
    for (var i=0; i < response.total_rows; i++) { 
    if (response.rows[i].doc.type == 'bar') { 
     var qc = {id: response.rows[i].doc._id, 
     isFoo: true 
     }; 
     var foo = oneFunction(qc); 
     foos.push(foo); 
    } 
    } 
    var promises = foos.map(anotherFunction); // make a promise for each foo 
    return $q.all(promises); 
}) 
+0

response.rows может быть 'map'd, так как это массив, отличный от этого выглядит хорошо :) –

+0

Да,' filter'ed и 'map'd, но я хотел оставаться рядом с исходным кодом. – Bergi

+0

с 'filter' вы имеете в виду https://www.npmjs.com/package/promise-filter? @Bergi – thadeuszlay

Смежные вопросы