javascript - CosmosDB uložené procedury - promise místo callbacku
Je možné použít JavaScriptové promises místo běžných callbacků v rámci volání API uložených procedur CosmosDB (DocumentDB)? Příkladem použití by byla implementace stránkování.
Například
token = getToken();
doSomething(token);
//....
function getToken(....) {
//...
collection.queryDocuments(link, query, queryOptions, function(error, documents, responseOptions) {
return responseOptions.continuation;
});
}
nebude fungovat, protože token je vrácen v rámci callbacku a provádění pokračuje. Mohl byste prosím uvést příklad, jak byste to implementoval?
Odpověď č. 1
Verze ECMAScript, na kterou se odkazuje dokumentace Cosmos DB, podporuje async/await a Promises. Oba tyto prvky mohu používat ve svých uložených procedurách.
Zde je funkce, která vrací promise, která provádí parametrizovaný dotaz na dokument:
function queryDocumentsAsync(sql, parameters, options) {
const querySpec = {
query: sql,
parameters: parameters
};
return new Promise((resolve, reject)=>{
let isAccepted = __.queryDocuments(__.getSelfLink(), querySpec, options || {}, (err, feed, options) => {
if(err) reject(err);
resolve({
feed: feed,
options: options
});
});
if(!isAccepted) throw "Query was not accepted.";
});
}
Vidím však určitá omezení při vynucování návratu zpět tímto přístupem. Pokud vyhodíte chybu, je pohlcena řetězcem promise a nikdy se ven nedostane.
Odpověď č. 2
Zde je příklad, jak použít async await pro scénář dotazu a nahrazení.
function async_sample() {
const ERROR_CODE = {
NotAccepted: 429
};
const asyncHelper = {
queryDocuments(sqlQuery, options) {
return new Promise((resolve, reject) => {
const isAccepted = __.queryDocuments(__.getSelfLink(), sqlQuery, options, (err, feed, options) => {
if (err) reject(err);
resolve({ feed, options });
});
if (!isAccepted) reject(new Error(ERROR_CODE.NotAccepted, "replaceDocument was not accepted."));
});
},
replaceDocument(doc) {
return new Promise((resolve, reject) => {
const isAccepted = __.replaceDocument(doc._self, doc, (err, result, options) => {
if (err) reject(err);
resolve({ result, options });
});
if (!isAccepted) reject(new Error(ERROR_CODE.NotAccepted, "replaceDocument was not accepted."));
});
}
};
async function main() {
let continuation;
do {
let { feed, options } = await asyncHelper.queryDocuments("SELECT * from c", { continuation });
for (let doc of feed) {
doc.newProp = 1;
await asyncHelper.replaceDocument(doc);
}
continuation = options.continuation;
} while (continuation);
}
main().catch(err => getContext().abort(err));
}
