如何将异步承诺功能重构为非异步以避免反模式
How to refactor async promise function to non async to avoid anti pattern
我正在尝试重构我使用反模式的代码,但仍然不明白如何重构这样的代码:
我现在有一个像这样工作的函数:
export async function submit(data) {
return new Promise(async function(resolve, reject) {
...
let list = await getList();
...
for (let i = 0; i < list.length; i++) {
let data = await getData(list[i]);
}
...
for (let i = 0; i < list.length; i++) {
let response = await uploadFile(list[i]);
}
我这样称呼这个函数:
let response = await submit(data);
我知道新 Promise 中的异步函数有问题,但如何解决?
export async function submit(data) {
return new Promise(async function(resolve, reject) {
let files = getFiles();
let prepareUrlsResponse = await prepareUrls(paths);
if (prepareUrlsResponse.error === true) {
resolve( { success: false });
} else {
let blobs = [];
for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
let fileData = await RNFetchBlob.fs.stat(filePath);
blobs.push(fileData);
}
for (let i = 0; i < blobs.length; i++) {
let item = blobs[i];
let response = await uploadFile(
item.url,
item.blob
);
if (response && response.uploadSuccess === false) {
resolve( { success: false });
break;
}
}
}
api.post(
endpoint,
data,
response => {
if (response.ok) {
resolve( { success: true, response: response });
} else {
resolve( { success: false });
}
}
);
});
}
完全放弃这条线。您的 submit
已经是一个 async function
,您可以直接在其中使用 await
。无需围绕整个事物创建 new Promise
,您只需要 promisfy 调用 api.post
。您应该将其分解为一个返回承诺的单独函数,并像在您调用的其他函数上一样在其上使用 await
。
function postData(url, data) {
return new Promise(function(resolve, reject) {
// ^^^^^^^^ no `async` here!
api.post(url, data, resolve);
});
}
export async function submit(data) {
let files = getFiles();
let prepareUrlsResponse = await prepareUrls(paths);
if (prepareUrlsResponse.error === true) {
return { success: false };
} else {
let blobs = [];
for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
let fileData = await RNFetchBlob.fs.stat(filePath);
blobs.push(fileData);
}
for (let i = 0; i < blobs.length; i++) {
let item = blobs[i];
let response = await uploadFile(
item.url,
item.blob
);
if (response && response.uploadSuccess === false) {
return { success: false };
}
}
}
const response = await postData(endpoint, data);
if (response.ok) {
return { success: true, response: response });
} else {
return { success: false };
}
}
您当然可以内联 postData
调用并使用 const response = await new Promise(…);
,但您应该只包装回调部分而不是整个逻辑。
我正在尝试重构我使用反模式的代码,但仍然不明白如何重构这样的代码: 我现在有一个像这样工作的函数:
export async function submit(data) {
return new Promise(async function(resolve, reject) {
...
let list = await getList();
...
for (let i = 0; i < list.length; i++) {
let data = await getData(list[i]);
}
...
for (let i = 0; i < list.length; i++) {
let response = await uploadFile(list[i]);
}
我这样称呼这个函数:
let response = await submit(data);
我知道新 Promise 中的异步函数有问题,但如何解决?
export async function submit(data) {
return new Promise(async function(resolve, reject) {
let files = getFiles();
let prepareUrlsResponse = await prepareUrls(paths);
if (prepareUrlsResponse.error === true) {
resolve( { success: false });
} else {
let blobs = [];
for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
let fileData = await RNFetchBlob.fs.stat(filePath);
blobs.push(fileData);
}
for (let i = 0; i < blobs.length; i++) {
let item = blobs[i];
let response = await uploadFile(
item.url,
item.blob
);
if (response && response.uploadSuccess === false) {
resolve( { success: false });
break;
}
}
}
api.post(
endpoint,
data,
response => {
if (response.ok) {
resolve( { success: true, response: response });
} else {
resolve( { success: false });
}
}
);
});
}
完全放弃这条线。您的 submit
已经是一个 async function
,您可以直接在其中使用 await
。无需围绕整个事物创建 new Promise
,您只需要 promisfy 调用 api.post
。您应该将其分解为一个返回承诺的单独函数,并像在您调用的其他函数上一样在其上使用 await
。
function postData(url, data) {
return new Promise(function(resolve, reject) {
// ^^^^^^^^ no `async` here!
api.post(url, data, resolve);
});
}
export async function submit(data) {
let files = getFiles();
let prepareUrlsResponse = await prepareUrls(paths);
if (prepareUrlsResponse.error === true) {
return { success: false };
} else {
let blobs = [];
for (let i = 0; i < prepareUrlsResponse.data.length; i++) {
let fileData = await RNFetchBlob.fs.stat(filePath);
blobs.push(fileData);
}
for (let i = 0; i < blobs.length; i++) {
let item = blobs[i];
let response = await uploadFile(
item.url,
item.blob
);
if (response && response.uploadSuccess === false) {
return { success: false };
}
}
}
const response = await postData(endpoint, data);
if (response.ok) {
return { success: true, response: response });
} else {
return { success: false };
}
}
您当然可以内联 postData
调用并使用 const response = await new Promise(…);
,但您应该只包装回调部分而不是整个逻辑。