Rimozione delle promesse nidificate

Sono nuovo alle promesse e alla scrittura di codice di rete usando richieste e promesse in NodeJS.

Vorrei rimuovere queste promesse nidificate e incatenarle invece, ma non sono sicuro di come andrei a farlo / se è la strada giusta da percorrere.

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); }); }); }); }; 

Questo è il codice di richiesta:

 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); }); }); } 

Qualsiasi intuizione sarebbe apprezzata.

Da ogni callback, dovrai restituire la nuova promise:

 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); }); }; 

La promise che viene restituita dalla chiamata .then() verrà quindi risolta con il valore della promise “inner”, in modo che sia ansible .then() facilmente.

Modello generico:

 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 

Promise.prototype.then è progettato per restituire un’altra promise, in modo da poterli concatenare.

La funzione di gestione passata a .then() può restituire un valore normale , come un numero o una stringa o un object, e questo valore verrà passato al gestore successivo di .then() .

Un’opzione è che boxViewerRequestSync sia una funzione sincrona che restituisce un object 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); }) 

Ma ovviamente il tuo boxViewerRequest è asincrono e restituisce invece una promise. In tal caso, la funzione di gestione passata a .then() potrebbe anche restituire una Promise completamente indipendente . Questa nuova promise viene eseguita in modo sincrono e, una volta risolta / rifiutata, il suo risultato viene passato al gestore successivo.

 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); }) 

Tenere traccia di tutte le promesse è confuso, ma la linea di fondo è questa: Promise.prototype.then restituirà sempre un object Promise, ma la funzione del gestore passata a Promise.prototype.then può restituire qualsiasi cosa, anche indefinita, o anche un’altra promise . Quindi quel valore, o il valore della Promessa risolta, viene passato alla funzione di gestione successiva.