如何将使用多个回调的JavaScript函数转换为使用承诺?

如何将使用多个回调的JavaScript函数转换为使用承诺?,javascript,promise,callback,es6-promise,Javascript,Promise,Callback,Es6 Promise,我正在尝试将使用异步函数的方式从回调转换为承诺 我理解这里显示的这种基本转换,其中回调被转换为resolve和reject函数: // CALLBACK const getData = (id, callback) => { setTimeout(() => { if (!id) return callback('ERROR: id is missing') return callback("The data for id "

我正在尝试将使用异步函数的方式从回调转换为承诺

我理解这里显示的这种基本转换,其中回调被转换为
resolve
reject
函数:

// CALLBACK
const getData = (id, callback) => {
    setTimeout(() => {
        if (!id) return callback('ERROR: id is missing')
        return callback("The data for id " + id);
    }, 1000)
};

getData(111, console.log);
getData(222, console.log);
getData(null, console.log);

// PROMISE
const getData2 = id => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (!id) reject('id is missing');
            resolve("The data for id " + id);
        }, 1000);
    });
};
getData2(333).then(console.log).catch((message) => console.log("ERROR: " + message));
getData2(444).then(console.log).catch((message) => console.log("ERROR: " + message));
getData2(null).then(console.log).catch((message) => console.log("ERROR: " + message));
但是我经常在下面的场景中使用回调,在这个场景中,您可以有一个需要很长时间的进程,并在调用代码处理信息时,通过多次回调向调用代码发送数据位:

sleep = function (ms) {
    var start = new Date().getTime();
    let now = 0;
    let difference = 0;
    for (var i = 0; i < 1e17; i++) {
        now = new Date().getTime();
        difference = now - start;
        if (difference > ms) {
            break;
        }
    }
}

const goShopping = (list, cbItemReport, cbFinished, cbError) => {
    let count = 0;
    let numberFound = 0;

    const randomError = Math.floor(Math.random() * 3);
    if (randomError == 0) {
        cbError('Something went wrong, trip aborted.');
    } else {
        list.forEach(item => {
            const randomFound = Math.floor(Math.random() * 4);
            if (randomFound > 0) {
                cbItemReport(item, true, ++count);
                numberFound++;
            } else {
                cbItemReport(item, false, ++count);
            }
            sleep(1000);
        })
        cbFinished(`Bought ${numberFound} things.`);
    }
}

goShopping(['milk', 'eggs', 'sugar', 'bread'],
    (item, found, count) => {
        console.log(`Item #${count} "${item}" was ${found ? 'found' : 'not found'}.`);
    },
    (message) => {
        console.log("Returned from shopping: " + message);
    },
    (error) => {
        console.log("ERROR: " + error);
    });
sleep=function(毫秒){
var start=new Date().getTime();
现在设=0;
设差=0;
对于(变量i=0;i<1e17;i++){
现在=新日期().getTime();
差异=现在-开始;
如果(差异>毫秒){
打破
}
}
}
const goShopping=(列表、cbItemReport、cbFinished、cbError)=>{
让计数=0;
设numberFound=0;
const randomError=Math.floor(Math.random()*3);
如果(随机错误==0){
cbError('发生故障,跳闸中止');
}否则{
list.forEach(项=>{
const randomFound=Math.floor(Math.random()*4);
如果(发现的随机数>0){
cbItemReport(项,真,++计数);
numberFound++;
}否则{
cbItemReport(项,假,++计数);
}
睡眠(1000);
})
cbFinished(`bunded${numberFound}things.`);
}
}
goShopping([‘牛奶’、‘鸡蛋’、‘糖’、‘面包’),
(项目、找到、计数)=>{
log(`Item#${count}${Item}是${found?'found':'notfound}.`);
},
(信息)=>{
console.log(“购物返回:+消息”);
},
(错误)=>{
日志(“错误:+错误”);
});

我将如何将后面使用的回调转换为承诺?在这种情况下,三个回调
cbItemReport
cbFinished
cbError
太多,无法映射到Promise拥有的两个回调,即仅
resolve
(cbFinished)和
reject
(cbError),或者我缺少什么?

cbFinished
调用
resolve
cbError
中拒绝
,并编写一个
cbItemReport
,它可以对每个项目执行您希望它执行的操作,就像在现有代码中一样。

从它听起来的样子来看,您希望实现类似于RxJs库的功能,那么为什么不直接使用它呢

查看RxJs

例如,一个呼叫可能如下所示:

const sub = new Subject(); // Create a subject 

sub.asObservable().subscribe( // Subscribe to that subject as obserable
    ({item, found, count}) => { // next
        console.log(`Item #${count} "${item}" was ${found ? 'found' : 'not found'}.`);
    },
    error => { // error
        console.log("ERROR: " + error);
    },
    message => { // complete
        console.log("Returned from shopping: " + message);
    }
);

const goShopping = (list) => {
    let count = 0;
    let numberFound = 0;

    const randomError = Math.floor(Math.random() * 3);
    if (randomError == 0) {
        sub.error('Something went wrong, trip aborted.'); // push an error to the subject
    } else {
        list.forEach(item => {
            const randomFound = Math.floor(Math.random() * 4);
            if (randomFound > 0) {
                sub.next({item: item, found: true, count: ++count}); // push a result to subject (single object)
                numberFound++;
            } else {
                sub.next({item: item, found: true, count: ++count}); // same as above
            }
            sleep(1000);
        })
        sub.complete(`Bought ${numberFound} things.`); // push complete to subject. after that no next is allowed anymore
    }
}

goShopping(['milk', 'eggs', 'sugar', 'bread'])