- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我找到了之前的帖子 ( How to perform same action regardless of promise fulfilment? ),但它已经有 5 年历史了,并且引用 winjs 是一个拼凑。
我想做的是加载数据元素列表。我有列表的本地副本和元素的本地副本 - 但它们可能在服务器端发生了变化。
该过程应该像这样工作:将列表从数据库加载到本地存储(与本地存储进行比较)-->然后从列表中列出的数据库加载(多个)数据元素。
因此,如果“loadList”异步函数成功...我想运行“loadElements”异步函数。如果 loadList 函数拒绝...我仍然想运行“loadElements”函数(它会触发多个获取请求 - 每个元素一个)。
“使用‘最后’”我听到你说...但我想将“loadList”解析/拒绝和“loadElements”解析/拒绝函数的结果传递给调用函数。据我所知,“finally”不会接收或传递属性。
我想将结果传递给调用函数的原因是查看拒绝原因是否是可接受的原因以及我是否可以信任本地副本作为权威副本(例如,如果数据库不包含LIST,我可以相信本地列表是权威版本)...所以我需要一种方法来分析调用函数中的“失败”。
这是我所拥有的:
export function syncLinkTablesAndElementsWithDB(username) {
return (dispatch, getState) => {
return new Promise((resolve, reject) => {
dispatch(loadLinkTableAndElementsFromDB(STATIONS_LINK_TABLE_TYPE, username))
.then((msg) => {
console.log("loadLinkTableAndElementsFromDB RESOLVED: ", msg);
resolve(msg)
})
.then(() => {
dispatch(pushLinkTableToDB(STATIONS_LINK_TABLE_TYPE, username))
dispatch(pushAllUserStationsToDB(username))
})
.catch((allPromReasons) => {
console.log("loadLinkTableAndElementsFromDB REJECTED: ", allPromReasons);
allReasonsAcceptable = true;
allPromReasons.forEach(reason => {
if (!isAcceptableLoadFailureReasonToOverwrite(reason)) {
allReasonsAcceptable = false;
}
});
if (allReasonsAcceptable) {
//TODO: DO push of local to DB
// eventually return results of the push to DB...
} else {
reject(allPromReasons)
}
})
});
}
}
export function loadLinkTableAndElementsFromDB(tableType, username) {
return (dispatch, getState) => {
return new Promise((resolve, reject) => {
dispatch(loadLinkTableFromDB(tableType, username))
.then(successMsg => {
resolve(Promise.all([successMsg, dispatch(loadAllUsersStationsFromDB(username)).catch(err=>err)]))
})
.catch(err => {
reject(Promise.all([err, dispatch(loadAllUsersStationsFromDB(username)).catch(err=>err)]))
})
});
}
}
export function loadAllUsersStationsFromDB(username) {
return (dispatch, getState) => {
return new Promise((resolve, reject) => {
let linkTable = getStationsLinkTable(username); // get the local link table
if (linkTable && Array.isArray(linkTable.stations)) { // if there is a local station list
let loadPromises = linkTable.stations.map(stationID => dispatch(loadStationFromDB(stationID)).catch((err) => err));
Promise.all(loadPromises)
.then((allReasons) => {
let allSuccesses = true;
allReasons.forEach(reason => {
if (!reason.startsWith(SUCCESS_RESPONSE)) {
allSuccesses = false;
}
});
if (allSuccesses) {
resolve(SUCCESS_RESPONSE + ": " + username);
} else {
reject(allReasons);
}
})
} else {
return reject(NO_LINK_TABLE_AVAILABLE + ": " + username);
}
});
};
}
loadStationFromDB 和 loadLinkTableFromDB 执行您所期望的操作...尝试从数据库加载这些内容。如果您认为值得,我可以包含他们的代码。
----------- 编辑 -----------为了澄清我想要完成的任务:
我正在尝试将本地存储与数据库同步。我想通过从数据库中提取数据,比较时间/日期戳来做到这一点。这将使本地存储版本成为所有数据的权威副本。从数据库加载后,我想将本地存储版本推送到数据库。
我需要注意这样一个事实:数据库通常根本没有数据,因此可能会“拒绝”拉取......即使在同步的情况下,拒绝是可以接受的,并且不应停止同步过程。
根据下面的建议,我修改了我的代码:
export function loadLinkTableAndElementsFromDB(tableType, username) {
console.log("loadLinkTableAndElementsFromDB(", tableType, username, ")");
return (dispatch, getState) => {
return new Promise((resolve, reject) => {
dispatch(loadLinkTableFromDB(tableType, username))
.then(successMsg => {
console.log("loadLinkTableFromDB RESOLVED: ", successMsg)
resolve(Promise.all([successMsg, dispatch(loadAllUsersStationsFromDB(username)).catch(err => err)]))
})
.catch(err => {
console.log("loadLinkTableFromDB REJECTED: ", err)
reject(Promise.all([err, dispatch(loadAllUsersStationsFromDB(username)).catch(err => err)]))
})
});
}
}
export function syncLinkTablesAndElementsWithDB(username) {
console.log("syncLinkTablesAndElementsWithDB(", username, ")");
return (dispatch, getState) => {
dispatch(loadLinkTableFromDB(STATIONS_LINK_TABLE_TYPE, username))
.then((successLoadLinkTableMsg) => {
console.log('Successfully loaded link table: ', successLoadLinkTableMsg)
return dispatch(pushLinkTableToDB(STATIONS_LINK_TABLE_TYPE, username))
})
.catch((rejectLoadLinkTableReason) => {
console.log("Failed to load link table from DB: " + rejectLoadLinkTableReason);
if (allReasonsAcceptableForOverwrite(rejectLoadLinkTableReason)) { // some rejection reasons are accectable... so if failed reason is okay....
console.log("Failure to load link table reasons were acceptable... pushing local link table anyway");
return dispatch(pushLinkTableToDB(STATIONS_LINK_TABLE_TYPE, username))
} else {
console.log("Throwing: ", rejectLoadLinkTableReason);
throw rejectLoadLinkTableReason;
}
})
.then((successPushLinkTaleMsg) => {
console.log("Successfully pushed link table: " + successPushLinkTaleMsg);
return dispatch(loadAllUsersStationsFromDB(username)); // I want this to occur regardless of if the link table stuff succeeds or fails... but it must occur AFTER the loadLinkTableFromDB at least tries...
})
.catch((rejectPushLinkTableReason) => {
console.log("Failed to push link table: " + rejectPushLinkTableReason);
return dispatch(loadAllUsersStationsFromDB(username)); // I want this to occur regardless of if the link table stuff succeeds or fails... but it must occur AFTER the loadLinkTableFromDB at least tries...
})
.then((successLoadAllUserStationsMsg) => {
console.log("Successfully loaded all user stations: " + successLoadAllUserStationsMsg);
return dispatch(pushAllUserStationsToDB(username))
})
.catch((rejectLoadAllUserStationsReason) => {
console.log("Failed to push all users stations: " + rejectLoadAllUserStationsReason);
if (allReasonsAcceptableForOverwrite(rejectLoadAllUserStationsReason)) { // some rejection reasons are accectable... so if failed reason is okay....
console.log("Load users stations reasons are acceptable...");
return dispatch(pushAllUserStationsToDB(username))
} else {
console.log("throwing: ", rejectLoadAllUserStationsReason);
throw rejectLoadAllUserStationsReason;
}
})
.then((successPushAllUserStationsMgs) => {
console.log("Successfully pushed all users stations: " + successPushAllUserStationsMgs);
return Promise.resolve();
})
.catch((rejectPushAllUserStationsReason) => {
console.log("Failed to push all users stations: " + rejectPushAllUserStationsReason);
throw rejectPushAllUserStationsReason;
})
};
}
export function syncAllWithDB(username) {
return (dispatch, getState) => {
// other stuff will occur here...
dispatch(syncLinkTablesAndElementsWithDB(username)) // *** Error here ***
.then((successMsg) => {
console.log("Successful sync for : " + successMsg);
})
.catch(allReasons => {
console.warn("Link tables and elements sync error: ", allReasons);
})
// });
}
}
不幸的是,我现在在syncAllWithDB函数中的调度上收到“TypeError:dispatch(...) is undefined”。此功能没有改变...
最佳答案
我并不完全遵循您想要实现的目标(更多内容见下文),但这里要做的第一件事是清理流程,而不是包装额外的 new Promise()
围绕现有的 promise 。从来没有理由这样做:
function someFunc() {
return new Promise((resolve, reject) => {
callSomething.then(result => {
...
doSomethingElse(result).then(result2 => {
...
resolve(result2);
}).catch(err => {
...
reject(err);
});
}).catch(err => {
...
reject(err);
});
});
}
这是一个众所周知的 promise 反模式。您不需要额外手动创建的 promise 包含在已经做出 promise 的函数中。相反,你可以只返回你已有的 promise 。这称为“ promise 链”。在链内,您可以从任何地方拒绝或解决该链。
function someFunc() {
return callSomething.then(result => {
...
// return promise here, chaining this new async operation
// to the previous promise
return doSomethingElse(result).then(result2 => {
...
return result2;
}).catch(err => {
...
// after doing some processing on the error, rethrow
// to keep the promise chain rejected
throw err;
});
}).catch(err => {
...
reject err;
});
}
或者,您甚至可以像这样展平 promise 链:
function someFunc() {
return callSomething.then(result => {
...
return doSomethingElse(result);
}).then(result2 => {
...
return result2;
}).catch(err => {
...
throw err;
});
}
举个例子,您可以像这样简化 syncLinkTablesAndElementsWithDB()
:
export function syncLinkTablesAndElementsWithDB(username) {
return (dispatch, getState) => {
return dispatch(loadLinkTableAndElementsFromDB(STATIONS_LINK_TABLE_TYPE, username)).then((msg) => {
console.log("loadLinkTableAndElementsFromDB RESOLVED: ", msg);
dispatch(pushLinkTableToDB(STATIONS_LINK_TABLE_TYPE, username))
dispatch(pushAllUserStationsToDB(username))
// have msg be the resolved value of the promise chain
return(msg);
}).catch((allPromReasons) => {
console.log("loadLinkTableAndElementsFromDB REJECTED: ", allPromReasons);
let allReasonsAcceptable = allPromReasons.every(reason => {
return isAcceptableLoadFailureReasonToOverwrite(reason);
});
if (allReasonsAcceptable) {
//TODO: DO push of local to DB
// eventually return results of the push to DB...
} else {
// have promise stay rejected
throw allPromReasons;
}
});
}
}
至于你的问题的其余部分,你问的是:
So if the "loadList" async function succeeds... I want to run the "loadElements" async function. If the loadList function rejects... I STILL want to run the "loadElements" function (Which fires off multiple fetch requests - one for each element).
但是,您的代码中没有名为 loadList()
和 loadElements()
的函数,因此您迷失了方向,所以我不确定如何制作特定的代码建议。
在 Promise 链的 .then()
处理程序中,您可以执行三件事:
.then()
处理程序都会自动监视异常,如果抛出任何异常,则 Promise 链会自动拒绝并显示异常值设置为拒绝原因。因此,这为您提供了最终的灵 active ,可以使用值或错误来完成 Promise 链,或者将其链接到另一个 Promise(更多异步操作)。
关于javascript - 无论结果如何,在 promise 之后执行次要行动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59108421/
如何从 promise 中退出 promise ? perl6 文档没有提供简单的方法。例如: my $x = start { loop { # loop forever until "qui
我的用户 Controller 中有一个索引操作,其中我试图连续做两件事,并且在它们都有机会完成之前不执行所需的 res.json() 方法。 我有一个加入用户的友谊加入模型。一列是 friender
请帮我解释一下为什么日志结果有两种不同: 方式 1:每 1 秒顺序记录一次 方式 2:1 秒后记录所有元素。 // Way 1 let sequence = Promise.resolve(); [1
我的问题很简单。 Promise.all() 方法可以返回 Promise 吗?让我解释一下: function simpleFunction() { let queue = [];
我正在使用 Promise 从存储中读取文件并转换为 base64 字符串。我有图像数组,使用 RNFS 读取图像 const promise_Images = _Images.map(async (
如果使用非空数组调用 Promise.all 或 Promise.race,它们将返回一个待处理的 Promise: console.log(Promise.all([1])); // prints
Promise.all 是否可以在没有包装 promise 的情况下返回链的最后一个值? 如果不使用 await,它在我的上下文中不起作用 没有包装的例子: function sum1(x){ r
我一直在玩 promise,通常能想出如何处理好它们,但在这种情况下,我不知道如何删除一个 promise-wrapping level。 代码如下: let promise2 = promise1.
考虑以下嵌套的Promises结构: const getData = async() => { const refs = [{ name: "John33", age: 3
我已经阅读了 Promise/A+ 规范,但据我了解,还有诸如 Promise/A 和 Promise 之类的东西。它们之间有什么区别? Promise 和 Promise/A 规范也是如此吗?如果是
当我运行以下代码时: my $timer = Promise.in(2); my $after = $timer.then({ say "2 seconds are over!"; 'result'
以下简单的 promise 是发誓的,我不允许打破它。 my $my_promise = start { loop {} # or sleep x; 'promise re
我正在尝试扩展Promise: class PersistedPromise extends Promise { } 然后在派生类上调用静态resolve以直接创建一个已解决的Promise: Per
我有两个返回 promise 的函数,我独立使用它们作为: getLocal().then(...) 和 getWeb().then(...) 但是现在我遇到了一个奇怪的问题: 1) 我需要第三个
我不知道 promise.all 解决方案中的 promise.all 是否是一个好的实践。我不确定。 我需要从一组用户获取信息,然后通过此信息响应,我需要发送消息通知。 let userList =
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
我一直在尝试使用 queueMicrotask() 函数,但我没有弄清楚当回调是微任务时回调的优先级如何。查看以下代码: function tasksAndMicroTasks() { const
今年早些时候,我在 Pharo Smalltalk 参与了一个 promise 项目。这个想法是为了实现以下行为: ([ 30 seconds wait. 4 ]promiseValue )then:
大家好,提前感谢您的帮助。 下面是我正在尝试做的事情 function1(){ throw some error(); } function2() { // dosomething suc
我有以下未解析的代码。f2 解决了,所以我不会添加该代码,它是 f1 我有问题。 我调用函数,它到达最里面如果,它调用函数“find”,它执行函数 findId,完美返回 Id,然后执行 editId
我是一名优秀的程序员,十分优秀!