- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有这样的情况:
async function thirdPartyCode(a) {
if (a == ...) {
return myPromiser(...) // can allow and act on this
}
let b = await someoneElsesPromiserB(...)
if (b == ...) {
let c = await myPromiser(...) // must error on this
...
}
let d = await someoneElsesPromiserD(...)
let e = myPromiser(...) // note no await
return e // can allow and act on this
}
作为 myPromiser() 的作者和此 thirdPartyCode() 的调用者,我想检测 myPromiser() 的 promise 是否用作异步函数的返回 promise 。这是在这种特殊类型的异步函数的调用上下文中使用它的唯一合法方式。当它在此函数内时,不能等待它,也不能附加 .then() 子句。
如果有办法知道“异步函数的主体何时实际上完成”,那将是解决它的一个楔子。
(注意:这个问题中的奇怪限制是使用 Emscripten Emterpreter 的副产品。当 simulated pthreads 可通过 WebAssembly worker/SharedArrayBuffer 等获得时,这些限制可能(?)不需要适用。但在撰写本文时,这些前沿浏览器功能并未默认启用……因此,这种不寻常的愿望来自于希望兼容的代码子集是合法的。)
最佳答案
你的问题很复杂,我可能在某些方面理解错了。但这里有 3-4 个想法可能会有所帮助。
想法一
从“then”开始,您可以使用 Proxy 立即调用“handler”,这几乎禁止对其进行的所有操作。完成此操作后,您只需观察函数退出或抛出错误即可。通过这种方式,您可以跟踪返回值是否以任何方式实际使用。
但是,如果未使用返回值 - 您将看不到它。所以这允许这种用途:
... some code ...
await myPromiser(); // << notice the return value is ignored
... some more code ...
如果这对您来说是个问题,那么此方法只能起到部分帮助。但如果这是一个问题,那么你最后一次调用 (let e = myPromiser(...)) 也将毫无用处,因为之后可以忽略“e”。
下面,在这个答案的末尾成功区分三种情况的 javascript 代码
想法 2
您可以在调用“thirdPartyCode”代码之前使用 Babel 检测它。如果需要,Babel 也可以在运行时使用。有了它,您可以:2.1 找出myPromise的所有用法并检查其是否合法。2.2 在每个 await 或 '.then' 之后添加对一些标记函数的调用 - 这样您就可以使用选项 1 检测所有情况。
答案 3
如果您正在寻找一种方法来了解 Promise 是您的还是已解决 - 那么答案是“没有这种方法”。证明(以Chrome运行为例):
let p = new Promise((resolve, reject)=>{
console.log('Code inside promise');
resolve(5);
});
p.then(()=>{
console.log('Code of then')
})
console.log('Code tail');
// Executed in Chrome:
// Code inside promise
// Code tail
// Code of then
这告诉我们 resolve 的代码总是在当前调用上下文之外执行。IE。我们可能一直期望从 Promise 内部调用“resolve”会导致立即调用所有订阅的函数,但事实并非如此——v8 将等到当前函数执行结束,然后才执行处理程序。
想法4(部分)
如果你想拦截对 SystemPromise.then 的所有调用并决定你的 Promiser 是否被调用 - 有一种方法:你可以用你的实现覆盖 Promise.then。
不幸的是,这不会告诉您异步功能是否结束。我已尝试对其进行试验 - 请参阅下面我的代码中的注释。
答案1的代码:
let mySymbol = Symbol();
let myPromiserRef = undefined;
const errorMsg = 'ANY CUSTOM MESSAGE HERE';
const allForbiddingHandler = {
getPrototypeOf: target => { throw new Error(errorMsg); },
setPrototypeOf: target => { throw new Error(errorMsg); },
isExtensible: target => { throw new Error(errorMsg); },
preventExtensions: target => { throw new Error(errorMsg); },
getOwnPropertyDescriptor: target => { throw new Error(errorMsg); },
defineProperty: target => { throw new Error(errorMsg); },
has: target => { throw new Error(errorMsg); },
get: target => { throw new Error(errorMsg); },
set: target => { throw new Error(errorMsg); },
deleteProperty: target => { throw new Error(errorMsg); },
ownKeys: target => { throw new Error(errorMsg); },
apply: target => { throw new Error(errorMsg); },
construct: target => { throw new Error(errorMsg); },
};
// We need to permit some get operations because V8 calls it for some props to know if the value is a Promise.
// We tell it's not to stop Promise resolution sequence.
// We also allow access to our Symbol prop to be able to read args data
const guardedHandler = Object.assign({}, allForbiddingHandler, {
get: (target, prop, receiver) => {
if(prop === mySymbol)
return target[prop];
if(prop === 'then' || typeof prop === 'symbol')
return undefined;
throw new Error(errorMsg);
},
})
let myPromiser = (...args)=> {
let vMyPromiser = {[mySymbol]:[...args] };
return new Proxy(vMyPromiser,guardedHandler);
// vMyPromiser.proxy = new Proxy(vMyPromiser,guardedHandler);
// vMyPromiser.then = ()=> {
// myPromiserRef = vMyPromiser;
// console.log('myPromiserThen - called!');
// return vMyPromiser.proxy;
// }
// return vMyPromiser;
};
let someArg = ['someArgs1', 'someArgs2'];
const someoneElsesPromiserB = async(a)=>{
return a;
}
const someoneElsesPromiserD = async(a)=>{
return a;
}
async function thirdPartyCode(a) {
console.log('CODE0001')
if (a == 1) {
console.log('CODE0002')
return myPromiser(a, someArg) // can allow and act on this
}
console.log('CODE0003')
let b = await someoneElsesPromiserB(a)
console.log('CODE0004')
if (b == 2) {
console.log('CODE0005')
let c = await myPromiser(a, someArg) // must error on this
console.log('CODE0006')
let x = c+5; // <= the value should be used in any way. If it's not - no matter if we did awaited it or not.
console.log('CODE0007')
}
console.log('CODE0008')
let d = await someoneElsesPromiserD(a);
console.log('CODE0009')
let e = myPromiser(a, someArg) // note no await
console.log('CODE0010')
return e // can allow and act on this
};
// let originalThen = Promise.prototype.then;
// class ReplacementForPromiseThen {
// then(resolve, reject) {
// // this[mySymbol]
// if(myPromiserRef) {
// console.log('Trapped then myPromiser - resolve immediately');
// resolve(myPromiserRef.proxy);
// myPromiserRef = undefined;
// } else {
// console.log('Trapped then other - use System Promise');
// originalThen.call(this, resolve, reject);
// }
// }
// }
//
// Promise.prototype.then = ReplacementForPromiseThen.prototype.then;
(async()=>{
let r;
console.log('Starting test 1');
r = await thirdPartyCode(1);
console.log('Test 1 finished - no error, args used in myPromiser = ', r[mySymbol]);
console.log("\n\n\n");
console.log('Starting test 3');
r = await thirdPartyCode(3);
console.log('Test 3 finished - no error, args used in myPromiser = ', r[mySymbol]);
console.log("\n\n\n");
console.log('Starting test 2 - should see an error below');
r = await thirdPartyCode(2);
})();
关于javascript - 检测异步函数的 "returned promise only"状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55186667/
如何从 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
我是一名优秀的程序员,十分优秀!