2014-02-24 129 views
13

我不熟悉承諾和使用NodeJS中的請求和承諾編寫網絡代碼。刪除嵌套承諾

我想刪除這些嵌套的承諾,並鏈接它們,但我不知道我會怎麼做/是否是正確的方式。

exports.viewFile = function(req, res) { 
var fileId = req.params.id; 
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken) 
    .then(function(response) { 
     boxViewerRequest('documents', {url: response.request.href}, 'POST') 
      .then(function(response) { 
       boxViewerRequest('sessions', {document_id: response.body.id}, 'POST') 
        .then(function(response) { 
         console.log(response); 
        }); 
      }); 
    }); 
}; 

這是請求代碼:

var baseContentURL = 'https://api.box.com/2.0/'; 
var baseViewerURL = 'https://view-api.box.com/1/'; 

function boxContentRequest(url, accessToken) { 
    return new Promise(function (resolve, reject) { 
      var options = { 
       url: baseContentURL + url, 
       headers: { 
        Authorization: 'Bearer ' + accessToken, 
       } 
      }; 
     request(options, function (err, res) { 
     if (err) { 
      return reject(err); 
     } else if (res.statusCode !== 200) { 
      err = new Error("Unexpected status code: " + res.statusCode); 
      err.res = res; 
      return reject(err); 
     } 
     resolve(res); 
     }); 
    }); 
} 

function boxViewerRequest(url, body, method) { 
    return new Promise(function (resolve, reject) { 
      var options = { 
       method: method, 
       url: baseViewerURL + url, 
       headers: { 
        Authorization: 'Token ' + config.box.viewerApiKey 
       }, 
       json: body 
      }; 
     request(options, function (err, res, body) { 
     if (err) { 
      return reject(err); 
     } else if (res.statusCode !== 200 && res.statusCode !== 201 && res.statusCode !== 202) { 
      err = new Error("Unexpected status code: " + res.statusCode); 
      err.res = res; 
      return reject(err); 
     } 
     resolve(res, body); 
     }); 
    }); 
} 

任何瞭解,將不勝感激。

+0

您可能需要[請求 - 承諾](https://github.com/tyabonil/request-promise)。有了這個lib,你可以保存一些代碼來將請求包裝到承諾中。 –

回答

20

從每then回調,則需要回報新的承諾:

exports.viewFile = function(req, res) { 
    var fileId = req.params.id; 
    boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken) 
     .then(function(response) { 
      return boxViewerRequest('documents', {url: response.request.href}, 'POST'); 
     }) 
     .then(function(response) { 
      return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST'); 
     }) 
     .then(function(response) { 
      console.log(response); 
     }); 
}; 

一個由.then()調用返回,然後會從「內部」的承諾價值解決的承諾,所以你很容易就可以鏈接它們。

通用模式:

somePromise.then(function(r1) { 
    return nextPromise.then(function(r2) { 
     return anyValue; 
    }); 
}) // resolves with anyValue 

    || 
    \||/ 
    \/ 

somePromise.then(function(r1) { 
    return nextPromise; 
}).then(function(r2) { 
    return anyValue; 
}) // resolves with anyValue as well 
0

Promise.prototype.then旨在返回另一個承諾,這樣就可以把它們連。

傳遞給.then()處理函數可以返回一個正常值,像一個數字或字符串或對象,這個值將坐上去的.then()下一個處理過。

一種選擇是有boxViewerRequestSync是同步函數返回一個response對象:

boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken) 
    .then(function(response) { 
     return boxViewerRequestSync('documents', {url: response.request.href}, 'POST') 
    }) 
    .then(function(response) { // this `response` is returned by `boxViewerRequestSync` 
     return boxViewerRequestSync('sessions', {document_id: response.body.id}, 'POST') 
    }) 
    .then(function(response) { 
     console.log(response); 
    }) 

但當然你boxViewerRequest是異步的,並返回一個承諾來代替。在這種情況下,處理函數傳遞給.then()也可能返回completely unrelated Promise。這個新的承諾是同步執行的,一旦它被解析/拒絕,它的結果被傳遞到下一個處理程序。所有承諾的

boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken) 
    .then(function(response) { 
     return boxViewerRequest('documents', {url: response.request.href}, 'POST') 
    }) 
    .then(function(response) { // this `response` is the result of resolving the promise returned by `boxViewerRequest` 
     return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST') 
    }) 
    .then(function(response) { 
     console.log(response); 
    }) 

飼養的軌道是混亂的,但底線是這樣的:Promise.prototype.then總是返回無極對象,但處理函數傳遞Promise.prototype.then可以返回任何東西,甚至是不確定的,或者甚至是另一個承諾。然後,該值或解析的Promise的值將傳遞給下一個處理函數。