2015-03-05 3 views
2

Предположим, что у меня есть модуль «JsonEditor» (только для примера), который имеет 3 функции: get(), setProperty() и save().Как перенести решение обещания() на другое обещание

Вот код (вопрос следующим образом):

var fs = require('fs') 
    , q = require('q'); 

var jsonEditorModule = (function() { 
    return { 
     get: function(jsonPath) { 
      // ... 
     }, 

     save: function(jsonObject, jsonPath) { 
      var qJson = q.defer(); 

      var jsonContent = JSON.stringify(jsonObject, null, 2); 

      fs.writeFile(jsonPath, jsonContent, function(err) { 
       if(err) { 
        qJson.reject(err); 
       } 
       else { 
        qJson.resolve(); 
       } 
      }); 

      return qJson.promise; 
     }, 

     setProperty: function(prop, value, jsonPath) { 
      var self = this; 
      var qJson = q.defer(); 

      this.get(jsonPath) 
      .then(
       function(jsonObject) { 
        // Set the property 
        jsonObject[prop] = value; 

        // Save the file 
        self.save(jsonObject, jsonPath) 
        .then(
         function() { 
          qJson.resolve(); 
         }, 
         function() { 
          qJson.reject(); 
         }, 
        ); 
       } 
      ); 

      return qJson.promise; 
     }, 
    }; 
})(); 

module.exports = jsonEditorModule; 

Смотрите затем() сразу после сохранения() в функции SetProperty()?

Это выглядит глупо, правда?

Нужно ли вручную разрешать() и отклонять() мое обещание? Могу ли я просто передать поведение save() моему обещанию setProperty()?

Надеюсь, что вопрос достаточно ясен (и не слишком глуп).

Благодаря

+0

Посмотрите здесь и посмотреть, если вы можете переделки вы называете структуру, чтобы создать цепочку http://stackoverflow.com/questions/12461589/how-do-i-do-a-callback-chain-with- q –

ответ

2

То, что вы хотите достичь описано здесь: chaining, в основном, если обработчик возвращает обещание (назовем его innerPromiseFromHandler), то обработчики в .then, который был определен на предыдущем обещание будет выполнено, если innerPromiseFromHandler получает значение разрешения:

var jsonEditorModule = (function() { 
 
    return { 
 
    get: function(jsonPath) { 
 
     return Q.delay(1000).then(function() { 
 
     document.write('get...<br/>'); 
 
     return 'get'; 
 
     }); 
 
    }, 
 

 
    save: function(result) { 
 
     return Q.delay(1000).then(function() { 
 
     document.write('save...<br/>');   
 
     return result + ' save'; 
 
     }); 
 
    }, 
 

 
    setProperty: function(prop, value, jsonPath) { 
 
     return this.get(jsonPath) 
 
     .then(function(result) { 
 
      return jsonEditorModule.save(result); 
 
     }); 
 
    } 
 
    }; 
 
})(); 
 
     
 
jsonEditorModule 
 
    .setProperty() 
 
    .then(function (result) {  
 
    document.write(result + ' finish'); 
 
    })
<script src="http://cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.js"></script>

+0

Объявление 'jsonEditorModule' вне IIFE довольно сильно поражает точку IIFE. Вы должны объявить его внутри и вернуть его. – JLRishe

+0

Даже если это модуль CommonJS, загруженный через require()? Я не скопировал конец моего файла, который является module.exports = jsonEditorModule; – Maslow

+0

Спасибо Маурисио. Это совершенно ясно (и событие лучше, а не снисходительно) – Maslow

2

Это выглядит глупо, не так ли? Нужно ли мне вручную resolve() и reject() мое обещание?

Право, и на самом деле это имеет свое имя: Ручное решение/отклонение дополнительного обещания известно как глупое deferred antipattern.

Могу ли я просто передать поведение save() моему setProperty() обещаниям?

Да, это тривиально возможно - и это встроенное в методе then: Вызов .then() возвращает новое обещание для return стоимости ваших обратных вызовов, даже если это значение скрыто в обещании.

var jsonEditorModule = { 
    get: function(jsonPath) { 
     // ... 
    }, 
    save: function(jsonObject, jsonPath) { 
     return Q.ninvoke(fs, "writeFile", jsonPath, JSON.stringify(jsonObject, null, 2)); 
    }, 
    setProperty: function(prop, value, jsonPath) { 
     return this.get(jsonPath).then(function(jsonObject) { 
//  ^^^^^^ 
      // Set the property 
      jsonObject[prop] = value; 
      // Save the file 
      return this.save(jsonObject, jsonPath); 
//   ^^^^^^ 
     }.bind(this)); 
    } 
}; 
Смежные вопросы