ygo*_*goe 5 javascript promise
我需要修改现有代码以支持同步和异步结果。虽然我可以轻松地使用 C# 处理Task和await,但即使在阅读了 MDN 和其他页面的大量内容之后,我还是无法理解 JavaScript Promise。
现有代码如下所示:
function dispatchCall() {
// ...
try {
let result = fn.apply(context, args);
if (result !== undefined) {
return { status: 0, result: result };
}
return { status: 0 };
}
catch (err) {
if (typeof err === "object") {
return { status: 400, errorMessage: err.name + ", " + err.message, stack: err.stack };
}
return { status: 400, errorMessage: err };
}
}
Run Code Online (Sandbox Code Playgroud)
fn是要调用的函数。它是由我的 API 的用户定义的,所以我不知道它会做什么。目前它总是返回一个值或抛出异常。该值将被包装在一个消息对象中,该对象被传递回 的远程调用者dispatchCall。
现在fn需要返回 a,Promise因为它将在结果无法立即可用的异步工作流程中使用。
我需要测试是否result是 a Promise(或“thenable”)并采取相应的行动。在这种情况下,当结果承诺得到解决时,我需要将结果值包装在适当的消息对象中,并将其作为另一个承诺传递给 的调用者dispatchCall。然后我就可以轻松地处理它。
就是那个“值的传递和修改”我解决不了。
我将这样开始:
function dispatchCall() {
// ...
try {
let result = fn.apply(context, args);
// --------------------------------------------------
if (result && typeof result.then === "function") {
result.then(function (result) {
// Like so?
if (result !== undefined) {
return { status: 0, result: result };
}
return { status: 0 };
})
.catch(function (err) {
// Does this catch errors?
if (typeof err === "object") {
return { status: 400, errorMessage: err.name + ", " + err.message, stack: err.stack };
}
return { status: 400, errorMessage: err };
});
return new Promise(function(resolve, reject) {
// What about this?
// When should I call resolve and reject and with what arguments?
});
// Must return a Promise and not continue at this point!
}
// --------------------------------------------------
if (result !== undefined) {
return { status: 0, result: result };
}
return { status: 0 };
}
catch (err) {
if (typeof err === "object") {
return { status: 400, errorMessage: err.name + ", " + err.message, stack: err.stack };
}
return { status: 400, errorMessage: err };
}
}
Run Code Online (Sandbox Code Playgroud)
这应该如何粘合在一起?
查看支持表后,我决定放弃 Internet Explorer 支持并使用 ES6 Promises。不涉及外部库。如果某些 IE 执行此操作,它应该继续使用同步函数,并允许在异步代码中严重失败。
我的目标环境是浏览器和 Node.js。
new Promise当你有 thenable 时,不需要创建一个 Promise 。
您可以只 return return result.then(......,或者如果您想确保返回一个 Promise 实例(而不仅仅是then().catch()返回的任何内容),则将结果传递给:Promise.resolve()
if (typeof result.then === "function") {
return Promise.resolve(result).then(function (result) {
if (result !== undefined) {
return { status: 0, result: result };
}
return { status: 0 };
})
.catch(function (err) {
if (typeof err === "object") {
return { status: 400, errorMessage: err.name + ", " + err.message, stack: err.stack };
}
return { status: 400, errorMessage: err };
});
}
Run Code Online (Sandbox Code Playgroud)
如果回调中发生错误catch,则返回的 Promise 将解析为被拒绝。调用者可以用自己的catch链接来处理这个问题。
由于结果可能会异步检索,因此使用者dispatchCall 必须具有等待可能异步数据返回的逻辑。一种选择是返回一个最终解析为您正在寻找的对象(或对象)dispatchCall的 Promise :{ status, result }{ status, error }
if (typeof result.then === "function") {
return result
.then((resolveValue) => {
return { status: 0, result: resolveValue };
})
.catch((error) => {
return { status: 400, error };
})
}
Run Code Online (Sandbox Code Playgroud)
在 的消费者中dispatchCall,检查返回的值是否是 Promise - 如果是,则调用.then它:
const dispatchResult = dispatchCall();
if (typeof dispatchResult.then === 'function') {
dispatchResult.then(({ status, result, error }) => {
// do stuff with status, result, error here
// if there was an error, result will be undefined
});
} else {
// do stuff with dispatchResult.status, .result, .errorMessage
}
Run Code Online (Sandbox Code Playgroud)
你也可以考虑不管是否result是 Promise 都返回一个 Promise,这样可以让代码更容易管理——例如在同步部分:
return Promise.resolve({ status: 0, result: result });
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9720 次 |
| 最近记录: |