如何将现有的回调API转换为Promise?

JavaScript

凯斯丁

2020-03-11

我想使用Promise,但是我有一个类似以下格式的回调API:

1. DOM加载或其他一次事件:

window.onload; // set to callback
...
window.onload = function() {

};

2.普通回调:

function request(onChangeHandler) {
    ...
}
request(function() {
    // change happened
    ...
});

3.节点样式回调(“ nodeback”):

function getStuff(dat, callback) {
    ...
}
getStuff("dataParam", function(err, data) {
    ...
})

4.带有节点样式回调的整个库:

API;
API.one(function(err, data) {
    API.two(function(err, data2) {
        API.three(function(err, data3) {
            ...
        });
    });
});

如何在Promise中使用API​​,如何“承诺”呢?

第684篇《如何将现有的回调API转换为Promise?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

6个回答
Stafan逆天前端 2020.03.11

大概晚了5年,但我想在这里发布我的promesify版本,该版本采用回调API的功能并将其转化为承诺

const promesify = fn => {
  return (...params) => ({
    then: cbThen => ({
      catch: cbCatch => {
        fn(...params, cbThen, cbCatch);
      }
    })
  });
};

在这里看看这个非常简单的版本:https : //gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a

伽罗Tony小卤蛋 2020.03.11

您可以在ES6中使用本地Promise,例如处理setTimeout:

enqueue(data) {

    const queue = this;
    // returns the Promise
    return new Promise(function (resolve, reject) {
        setTimeout(()=> {
                queue.source.push(data);
                resolve(queue); //call native resolve when finish
            }
            , 10); // resolve() will be called in 10 ms
    });

}

在这个例子中,承诺没有失败的理由,因此reject()永远不会被称为。

神奇古一 2020.03.11

你可以做这样的事情

// @flow

const toPromise = (f: (any) => void) => {
  return new Promise<any>((resolve, reject) => {
    try {
      f((result) => {
        resolve(result)
      })
    } catch (e) {
      reject(e)
    }
  })
}

export default toPromise

然后用

async loadData() {
  const friends = await toPromise(FriendsManager.loadFriends)

  console.log(friends)
}
AStafan 2020.03.11

kriskowal的Q库包含应答回调函数。这样的方法:

obj.prototype.dosomething(params, cb) {
  ...blah blah...
  cb(error, results);
}

可以用Q.ninvoke转换

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});
蛋蛋猿 2020.03.11

今天,我可以用PromiseNode.js作为一个普通的JavaScript方法。

一个简单的基本示例Promise(采用KISS方式):

普通 Javascript异步API代码:

function divisionAPI (number, divider, successCallback, errorCallback) {

    if (divider == 0) {
        return errorCallback( new Error("Division by zero") )
    }

    successCallback( number / divider )

}

Promise Javascript异步API代码:

function divisionAPI (number, divider) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            return rejected( new Error("Division by zero") )
        }

        fulfilled( number / divider )

     })

}

(我建议访问这个美丽的资源

Promise可以一起使用async\awaitES7,以使程序流程等待一个fullfiled像下面这样的结果:

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


async function foo () {

    var name = await getName(); // awaits for a fulfilled result!

    console.log(name); // the console writes "John Doe" after 3000 milliseconds

}


foo() // calling the foo() method to run the code

使用.then()方法使用相同代码的另一种用法

function getName () {

    return new Promise(function (fulfilled, rejected) {

        var name = "John Doe";

        // wait 3000 milliseconds before calling fulfilled() method
        setTimeout ( 
            function() {
                fulfilled( name )
            }, 
            3000
        )

    })

}


// the console writes "John Doe" after 3000 milliseconds
getName().then(function(name){ console.log(name) })

Promise也可以在基于Node.js的任何平台上使用,例如react-native

奖励混合方法
(假设回调方法具有两个参数,分别是错误和结果)

function divisionAPI (number, divider, callback) {

    return new Promise(function (fulfilled, rejected) {

        if (divider == 0) {
            let error = new Error("Division by zero")
            callback && callback( error )
            return rejected( error )
        }

        let result = number / divider
        callback && callback( null, result )
        fulfilled( result )

     })

}

上面的方法可以响应老式回调和Promise用法的结果。

希望这可以帮助。

小宇宙JinJinHarry 2020.03.11

我认为window.onload@Benjamin 建议不会一直有效,因为它无法检测到加载后是否被调用。我被很多次咬伤了。这是一个应该始终有效的版本:

function promiseDOMready() {
    return new Promise(function(resolve) {
        if (document.readyState === "complete") return resolve();
        document.addEventListener("DOMContentLoaded", resolve);
    });
}
promiseDOMready().then(initOnLoad);

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android