我经常发现自己使用类似于以下的模式:
const foo = () => {
const _resolve;
const promise = new Promise(resolve => _resolve = resolve);
myAsyncCall(_resolve);
return (dataWeDontHaveYet) => promise.then(cb => cb(dataWeDontHaveYet));
}
const finalData = async2(foo());
function async2(cb) {
... async stuff ...
return cb(dataWeDidntHaveBefore);
}
function myAsyncCall(cb) { return cb(somePrimitive); }
所以我想要立即启动异步调用,但是我需要根据我尚未拥有的数据来解决异步调用问题。
排序就像一个队列。
也许我不应该使用承诺?我不确定。我以前用过这个,但我找不到代码。目前我正在尝试将流转换为生成器并且遇到困难。
编辑:我创建了一个非常具体的问题的新问题,可以在How to convert a stream into a generator without leaking resolve from a promise
找到答案 0 :(得分:1)
你所拥有的语法并没有多大意义,所以希望我能在这个答案中走上正轨。
您还需要使用Promise或回调等待异步数据。你只需将它们连在一起并返回Promise的开头。
如果myAsyncCall()
也返回Promise
,则可以执行此操作:
return myAsyncCall();
这将返回Promise
,myAsyncCall()
将在then()
完成后解析。如果您需要转换该数据,可以将任意数量的return myAsyncCall().then(d => transform(d));
链接到其上:
myAsyncCall()
首先解析then()
,然后转换,然后随后的myAsyncCall()
调用将获得最新调用的内容。
如果Promise
使用回调,您可以返回return new Promise((resolve) => {
myAsyncCall(data => resolve(data));
});
:
myAsyncCall()
这将让Promise
解析,然后将该数据传递给const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);
a(1, result =>
b(result, newResult =>
console.log(newResult)
)
);
,然后将其用于其他事项。
更新后,我想我更了解您的需求。看起来你基本上只是想把回调和Promise连在一起。
首先,看看正常"回调"链接。
const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);
const onA = result => b(result, onB);
const onB = result => console.log(result);
a(1, onA);

这是链接的回调方式。基本上,您将函数作为参数传递,该参数接收作为前一个函数的结果的参数。
嵌套方法有点混乱,所以很多人会稍微分解一下:
Promises

then()
使用const a = start => Promise.resolve(start);
const b = input => Promise.resolve(input + 5);
a(1).then(b).then(result => console.log(result));
链接它们。以上所有Promise的工作方式如下:
const a = start => Promise.resolve(start);
const b = (input, cb) => cb(input + 5);
a(1).then(result => b(result, result => console.log(result)));

现在,当你需要混合两者时,有几种方法。一种是将它们以更直接的方式混合在一起:
promisify

这样可行,但会给你带来很多嵌套回调的混乱。
更清洁的方法是宣传"回调。虽然有些库可以为您执行此操作,但快速const promisify = func => (...args) => new Promise(resolve => {
const cb = result => resolve(result);
func.apply(func, args.concat(cb));
});
const a = (start, cb) => cb(start);
const b = (input, cb) => cb(input + 5);
const aPromisified = promisify(a);
const bPromisified = promisify(b);
aPromisified(1)
.then(bPromisified)
.then(result => console.log(result));
函数如下所示:
promisify

基本上,它只是将回调函数包装到Promise中。然后,您可以将其视为承诺。我对内置的Node库函数使用了这种方法。
如果您需要(err, result)
使用true
回调的典型节点格式,那么您可以使用此const promisify = (func, withErr = false) => (...args) => new Promise((resolve, reject) => {
const handler = (err, result) => {
if(withErr) {
err ? reject(err) : resolve(result);
} else {
resolve(err);
}
}
func.apply(func, args.concat(handler));
});
const aCallback = (start, cb) => cb(start);
const bCallback = (input, cb) => cb(input === 3 && 'cannot be 3', input + 5);
const a = promisify(aCallback);
const b = promisify(bCallback, true);
a(1).then(b).then(r => console.log(r));
a(3).then(b).catch(err => console.error(err));
并传入<input type="checkbox" '+PMS_Checked(campus_id)+'name="teacher_faculty_meta[semester_id]['+campus_id+']" value="'+campus_id+'">
以获取&#34; withErr&#34 ;:
return "checked='true'";
&#13;