如何避免从promises中提取解析,同时在回调之前启动进程?

时间:2018-01-31 16:55:26

标签: javascript promise generator

我经常发现自己使用类似于以下的模式:

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

找到

1 个答案:

答案 0 :(得分:1)

你所拥有的语法并没有多大意义,所以希望我能在这个答案中走上正轨。

您还需要使用Promise或回调等待异步数据。你只需将它们连在一起并返回Promise的开头。

如果myAsyncCall()也返回Promise,则可以执行此操作:

return myAsyncCall();

这将返回PromisemyAsyncCall()将在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 ;:

&#13;
&#13;
return "checked='true'";
&#13;
&#13;
&#13;