2015-03-10 2 views
0

Использование обещаний BlueBird, я пытаюсь сделать getCredentials в обещание, которое будет работать как getCredentials.then(function() { do this and that });. Не уверен, что я делаю неправильно, потому что, когда я разрешаю в writeToFile, обещание не считается разрешенным/полным.bluebird рекурсивное обещание не получается разрешено/заполнено

function getPassword(user) { 
    return new Promise(function(resolve, reject) { 
    read({prompt: "Password: ", silent: true, replace: "*" }, function (er, pass) { 
     rest.postJson(URL, payload(user, pass)) 
      .on('fail', httpFail) 
      .on('error', conError) 
      .on('success', writeToFile); 
    }); 
    }); 
} 

function getCredentials() { 
    return new Promise(function(resolve, reject) { 
    read({prompt: "Username: "}, function (er, user) { 
     getPassword(user); 
    }); 
    }); 
} 

function writeToFile(data, response) { 
    return new Promise(function(resolve, reject) { 
    tokenFile = 'gulp/util/token-file.json' 
    token = { 
     id: data.access.token.id, 
     expires: data.access.token.expires 
    } 
    token = JSON.stringify(token); 
    fs.writeFile(tokenFile, token, function(err) { 
     if (err) throw err; 
     console.log("Token was successfully retrieved and written to " .cyan + 
      tokenFile .cyan + "." .cyan); 
    resolve(); 
    }); 
    }); 
} 

module.exports = getCredentials; 
+1

Почему вы всегда игнорируете 'er'rors? Используйте правильное [promisification] (https://github.com/petkaantonov/bluebird/blob/master/API.md#promisification) вместо конструктора 'Promise'. – Bergi

+1

Что такое 'httpFail' и' conError'? – Bergi

+0

Это функции обратного вызова. Я попытался использовать обещание, но не имел успеха ... Я думал, что, возможно, некоторые из функций не соответствовали стандартам узлов. – dman

ответ

1

Не уверен, что я делаю неправильно, потому что, когда я решаю в WriteToFile обещание не учитывается как решенное/fullfilled

Ну, обещание, что ты вернулся из writeToFileявляется выполнено.
Но обещания, которые возвращаются с getPassword или getCredentials, никогда не были - вы не звоните ихresolve функции. Конструктор Promise не волшебным образом знает об асинхронных обратных вызовах, которые были использованы внутри него, или что были будут обещаниями, созданными в них.

Вы не можете сделать return что-нибудь от асинхронного обратного вызова, единственный способ оповестить результаты, вызвав другую функцию (обратный вызов). Внутри резонатора конструктора Promise это будут обратные вызовы resolve и reject.

Возможно, вы захотите посмотреть my rules for promise development. Мы почти никогда не используем конструктор Promise, только до promisify на минимально возможном уровне. В вашем случае, это было бы

function readAsync(options) { 
    return new Promise(function(resolve, reject) { 
     read(options, function (err, pass) { 
      if (err) reject(err); 
      else resolve(pass); 
     } 
    }); 
} 
function postAsync(url, payload) { 
    return new Promise(function(resolve, reject) { 
     rest.postJson(url, payload) 
     .on('fail', reject) 
     .on('error', reject) 
     .on('success', resolve); 
    }); 
} 

хотя с Bluebird мы можем упростить первый

var readAsync = Promise.promisify(read); 

и аналогичного назначения

var writeFileAsync = Promise.promisify(fs.writeFile, fs); 

Теперь, когда у нас есть эти обещания, возвращающие функции, мы можем применить остальные правила и составить их вместе, без необходимости использовать конструктор Promise:

function getPassword(user) { 
    return readAsync({prompt: "Password: ", silent: true, replace: "*" }) 
    .then(function(pass) { 
     return postAsync(URL, payload(user, pass)) 
    }); 
} 

function getCredentials() { 
    return readAsync({prompt: "Username: "}).then(getPassword); 
} 

function writeToFile(data, response) { 
    var tokenFile = 'gulp/util/token-file.json'; 
    var token = JSON.stringify({ 
     id: data.access.token.id, 
     expires: data.access.token.expires 
    }); 
    return writeFileAsync(tokenFile, token).then(function() { 
     console.log("Token was successfully retrieved and written to " .cyan + 
        tokenFile .cyan + "." .cyan); 
    }); 
} 

module.exports = getCredentials; 
+0

Этот пример и объяснение - невероятный учебный ресурс. Благодарю. – dman

1

getCredentials() и getPassword() не для решения своих обещаний, когда они будут завершены. Они никогда не решаются.

Я предполагаю из кода, что вы также хотите связать обещание getPassword с обещанием writeToFile, так что getPassword не будет разрешен до тех пор, пока не напишет writeToFile.

Это может выглядеть примерно так:

function getPassword(user) { 
    return new Promise(function(resolve, reject) { 
     read({prompt: "Password: ", silent: true, replace: "*" }, function (er, pass) { 
      rest.postJson(URL, payload(user, pass)) 
       .on('fail', httpFail) 
       .on('error', conError) 
       .on('success', function(data, response) { 
        writeToFile(data, response).then(resolve); 
       }); 
     }); 
    }); 
} 

Возможно, вы также хотите, чтобы реализовать обработку ошибок.

+0

Пожалуйста, не предлагайте отложенных Promise конструктор antipattern. – Bergi

+0

@Bergi - не стесняйтесь предлагать свой собственный ответ, который работает по-разному. – jfriend00

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