#javascript #node.js #asynchronous #firebase-authentication
#javascript #node.js #запрос #обещание
Вопрос:
Я новичок в promises и пишу сетевой код, используя запросы и обещания в 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 amp;amp; res.statusCode !== 201 amp;amp; res.statusCode !== 202) {
err = new Error("Unexpected status code: " res.statusCode);
err.res = res;
return reject(err);
}
resolve(res, body);
});
});
}
Любая информация будет оценена.
Комментарии:
1. Возможно, вас заинтересует Request-Promise . С помощью этой библиотеки вы сохраняете некоторый код для преобразования запроса в обещание.
Ответ №1:
При каждом 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
Ответ №2:
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()
, также может возвращать совершенно не связанные 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, но переданная функция-обработчик Promise.prototype.then
может возвращать что угодно, даже неопределенное, или даже другое обещание. Затем это значение или значение разрешенного обещания передается следующей функции-обработчику.