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

发布于 2025-01-30 06:38:45 字数 695 浏览 3 评论 0 原文

我想处理承诺,但我的回调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) {
            ...
        });
    });
});

我如何在承诺中与API一起工作,如何“诺言”?

I want to work with promises but I have a callback API in a format like:

###1. DOM load or other one time event:

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

};

###2. Plain callback:

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

###3. Node style callback ("nodeback"):

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

###4. A whole library with node style callbacks:

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

How do I work with the APIs in promises, how do I "promisify" them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(24

戴着白色围巾的女孩 2025-02-06 06:38:45

承诺有状态,他们开始待定,可以安定下来:

  • 实现意味着该计算成功完成。
  • 拒绝意味着计算失败。

承诺返回函数 永远不要扔 ,他们应该返回拒绝。从承诺返回功能中投掷将迫使您同时使用} catch { a .catch 。使用Promissied API的人不会期望承诺会抛弃。如果您不确定ASYNC API在JS中的工作原理 - 请请参阅此答案首先。

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

因此,创建承诺通常意味着指定何时定居 - 这意味着当它们移至满足或拒绝的阶段以指示数据可用(可以使用>。 /代码>)。

借助支持 Promise 构造函数的现代承诺实现,例如本机ES6承诺:

function load() {
    return new Promise(function(resolve, reject) {
        window.onload = resolve;
    });
}

然后,您将使用由此产生的承诺这样的承诺:

load().then(function() {
    // Do things after onload
});

使用支持延迟的库(让我们在此处使用$ Q稍后再使用jQuery):

function load() {
    var d = $q.defer();
    window.onload = function() { d.resolve(); };
    return d.promise;
}

或使用诸如API之类的jQuery,在发生的事件中挂钩:

function done() {
    var d = $.Deferred();
    $("#myObject").once("click",function() {
        d.resolve();
    });
    return d.promise();
}

2。纯回调:

这些API相当普遍,因为好吧……回调在JS中很常见。让我们看一下具有 OnSuccess onfail 的常见情况:

function getUserData(userId, onLoad, onFail) { …

具有支持 Promise> Promise> Promise 构造函数的现代承诺实现,例如本机ES6 Promises:

function getUserDataAsync(userId) {
    return new Promise(function(resolve, reject) {
        getUserData(userId, resolve, reject);
    });
}

带有图书馆 :支持延期(让我们在此处使用jQuery进行此示例,但是我们还使用了上面的$ q):

function getUserDataAsync(userId) {
    var d = $.Deferred();
    getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
    return d.promise();
}

jQuery还提供 $。$。递延(FN)表单,它具有允许我们写作的优势一种表达式,非常紧密地模拟新的Promise(FN)表格,如下:

function getUserDataAsync(userId) {
    return $.Deferred(function(dfrd) {
        getUserData(userId, dfrd.resolve, dfrd.reject);
    }).promise();
}

注意:在这里我们利用了一个事实,即jQuery deferred的 resolve and code> and recood> recood 方法是“可拆卸”; IE。它们被绑定到jQuery.deferred()的实例。并非所有的Libs都提供此功能。

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

节点样式回调(NodeBacks)具有特定格式,其中回调始终是最后一个参数,其第一个参数是错误。首先,让我们手动宣传一个:

getStuff("dataParam", function(err, data) { …

to:

function getStuffAsync(param) {
    return new Promise(function(resolve, reject) {
        getStuff(param, function(err, data) {
            if (err !== null) reject(err);
            else resolve(data);
        });
    });
}

使用延期,您可以执行以下操作(尽管Q现在支持新的语法您应该更喜欢):

function getStuffAsync(param) {
    var d = Q.defer();
    getStuff(param, function(err, data) {
        if (err !== null) d.reject(err);
        else d.resolve(data);
    });
    return d.promise;   
}

通常,您不应手动地承诺事物过多,大多数承诺库的库都考虑到节点,而Node 8+中的本机承诺具有构架方法,可以促进Nodebacks。例如

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

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

这里没有黄金规则,您可以一个人诺言。但是,某些承诺实现使您可以批量执行此操作,例如在蓝鸟中,将节点背API转换为Promise API很简单,就像:

Promise.promisifyAll(API);

native promises in node >:

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                         .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

注意:

  • 当然,当您在中。然后,当您不需要承诺事物时。从中返回承诺。然后,处理程序将通过该诺言的价值解决或拒绝。从中投掷。然后,处理程序也是一个很好的做法,并且会拒绝承诺 - 这是著名的承诺安全。
  • 在实际的 onload 情况下,您应该使用 addeventListener 而不是 onx

Promises have state, they start as pending and can settle to:

  • fulfilled meaning that the computation completed successfully.
  • rejected meaning that the computation failed.

Promise returning functions should never throw, they should return rejections instead. Throwing from a promise returning function will force you to use both a } catch { and a .catch. People using promisified APIs do not expect promises to throw. If you're not sure how async APIs work in JS - please see this answer first.

1. DOM load or other one time event:

So, creating promises generally means specifying when they settle - that means when they move to the fulfilled or rejected phase to indicate the data is available (and can be accessed with .then).

With modern promise implementations that support the Promise constructor like native ES6 promises:

function load() {
    return new Promise(function(resolve, reject) {
        window.onload = resolve;
    });
}

You would then use the resulting promise like so:

load().then(function() {
    // Do things after onload
});

With libraries that support deferred (Let's use $q for this example here, but we'll also use jQuery later):

function load() {
    var d = $q.defer();
    window.onload = function() { d.resolve(); };
    return d.promise;
}

Or with a jQuery like API, hooking on an event happening once:

function done() {
    var d = $.Deferred();
    $("#myObject").once("click",function() {
        d.resolve();
    });
    return d.promise();
}

2. Plain callback:

These APIs are rather common since well… callbacks are common in JS. Let's look at the common case of having onSuccess and onFail:

function getUserData(userId, onLoad, onFail) { …

With modern promise implementations that support the Promise constructor like native ES6 promises:

function getUserDataAsync(userId) {
    return new Promise(function(resolve, reject) {
        getUserData(userId, resolve, reject);
    });
}

With libraries that support deferred (Let's use jQuery for this example here, but we've also used $q above):

function getUserDataAsync(userId) {
    var d = $.Deferred();
    getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });
    return d.promise();
}

jQuery also offers a $.Deferred(fn) form, which has the advantage of allowing us to write an expression that emulates very closely the new Promise(fn) form, as follows:

function getUserDataAsync(userId) {
    return $.Deferred(function(dfrd) {
        getUserData(userId, dfrd.resolve, dfrd.reject);
    }).promise();
}

Note: Here we exploit the fact that a jQuery deferred's resolve and reject methods are "detachable"; ie. they are bound to the instance of a jQuery.Deferred(). Not all libs offer this feature.

3. Node style callback ("nodeback"):

Node style callbacks (nodebacks) have a particular format where the callbacks is always the last argument and its first parameter is an error. Let's first promisify one manually:

getStuff("dataParam", function(err, data) { …

To:

function getStuffAsync(param) {
    return new Promise(function(resolve, reject) {
        getStuff(param, function(err, data) {
            if (err !== null) reject(err);
            else resolve(data);
        });
    });
}

With deferreds you can do the following (let's use Q for this example, although Q now supports the new syntax which you should prefer):

function getStuffAsync(param) {
    var d = Q.defer();
    getStuff(param, function(err, data) {
        if (err !== null) d.reject(err);
        else d.resolve(data);
    });
    return d.promise;   
}

In general, you should not promisify things manually too much, most promise libraries that were designed with Node in mind as well as native promises in Node 8+ have a built in method for promisifying nodebacks. For example

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. A whole library with node style callbacks:

There is no golden rule here, you promisify them one by one. However, some promise implementations allow you to do this in bulk, for example in Bluebird, converting a nodeback API to a promise API is as simple as:

Promise.promisifyAll(API);

Or with native promises in Node:

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)}))
                         .reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

Notes:

  • Of course, when you are in a .then handler you do not need to promisify things. Returning a promise from a .then handler will resolve or reject with that promise's value. Throwing from a .then handler is also good practice and will reject the promise - this is the famous promise throw safety.
  • In an actual onload case, you should use addEventListener rather than onX.
秋心╮凉 2025-02-06 06:38:45

今天,我可以在 node.js 中使用 Promise 作为普通的JavaScript方法。

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

plin javaScript ASYNC API代码:

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

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

    successCallback( number / divider )

}

async 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 javascript //exploringjs.com/es6/ch_promises.html“ rel =“ noreferrer”>这个美丽的来源)

也可以一起使用 Promise 可以一起使用 async \ async \等待 es7 中,使程序流等待 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

使用

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-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 )

     })

}

上述方法可以响应旧的时尚回调和承诺用法的结果。

希望这会有所帮助。

Today, I can use Promise in Node.js as a plain Javascript method.

A simple and basic example to Promise (with KISS way):

Plain Javascript Async API code:

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

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

    successCallback( number / divider )

}

Promise Javascript Async API code:

function divisionAPI (number, divider) {

    return new Promise(function (fulfilled, rejected) {

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

        fulfilled( number / divider )

     })

}

(I recommend visiting this beautiful source)

Also Promise can be used with together async\await in ES7 to make the program flow wait for a fullfiled result like the following:

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

Another usage with the same code by using .then() method

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 can also be used on any platform that is based on Node.js like react-native.

Bonus: An hybrid method
(The callback method is assumed to have two parameters as error and result)

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 )

     })

}

The above method can respond result for old fashion callback and Promise usages.

Hope this helps.

友谊不毕业 2025-02-06 06:38:45

在将函数转换为Node.js

var request = require('request'); //http wrapped module

function requestWrapper(url, callback) {
    request.get(url, function (err, response) {
      if (err) {
        callback(err);
      }else{
        callback(null, response);             
      }      
    })
}


requestWrapper(url, function (err, response) {
    console.log(err, response)
})

转换后

var request = require('request');

function requestWrapper(url) {
  return new Promise(function (resolve, reject) { //returning promise
    request.get(url, function (err, response) {
      if (err) {
        reject(err); //promise reject
      }else{
        resolve(response); //promise resolve
      }
    })
  })
}


requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
    console.log(response) //resolve callback(success)
}).catch(function(error){
    console.log(error) //reject callback(failure)
})

Incase之前,您需要处理多个请求

var allRequests = [];
allRequests.push(requestWrapper('http://localhost:8080/promise_request/1')) 
allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))    

Promise.all(allRequests).then(function (results) {
  console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
  console.log(err)
});

Before converting a function as promise In Node.JS

var request = require('request'); //http wrapped module

function requestWrapper(url, callback) {
    request.get(url, function (err, response) {
      if (err) {
        callback(err);
      }else{
        callback(null, response);             
      }      
    })
}


requestWrapper(url, function (err, response) {
    console.log(err, response)
})

After Converting It

var request = require('request');

function requestWrapper(url) {
  return new Promise(function (resolve, reject) { //returning promise
    request.get(url, function (err, response) {
      if (err) {
        reject(err); //promise reject
      }else{
        resolve(response); //promise resolve
      }
    })
  })
}


requestWrapper('http://localhost:8080/promise_request/1').then(function(response){
    console.log(response) //resolve callback(success)
}).catch(function(error){
    console.log(error) //reject callback(failure)
})

Incase you need to handle multiple request

var allRequests = [];
allRequests.push(requestWrapper('http://localhost:8080/promise_request/1')) 
allRequests.push(requestWrapper('http://localhost:8080/promise_request/2'))
allRequests.push(requestWrapper('http://localhost:8080/promise_request/5'))    

Promise.all(allRequests).then(function (results) {
  console.log(results);//result will be array which contains each promise response
}).catch(function (err) {
  console.log(err)
});
老子叫无熙 2025-02-06 06:38:45

node.js 8.0.0包括新的 /a> API允许标准Node.js回调样式API包裹在返回承诺的函数中。 util.promisify()的示例使用如下所示。

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

readFile('/some/file')
  .then((data) => { /* ... */ })
  .catch((err) => { /* ... */ });

请参阅改进的承诺支持

Node.js 8.0.0 includes a new util.promisify() API that allows standard Node.js callback style APIs to be wrapped in a function that returns a Promise. An example use of util.promisify() is shown below.

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

readFile('/some/file')
  .then((data) => { /* ... */ })
  .catch((err) => { /* ... */ });

See Improved support for Promises

洛阳烟雨空心柳 2025-02-06 06:38:45

我认为@benjamin的建议 @benjamin不会一直工作,因为它无法检测到加载后是否调用它。我被这么多次咬了。这是一个应该始终工作的版本:

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

I don't think the window.onload suggestion by @Benjamin will work all the time, as it doesn't detect whether it is called after the load. I have been bitten by that many times. Here is a version which should always work:

function promiseDOMready() {
    return new Promise(function(resolve) {
        if (document.readyState === "complete") return resolve();
        document.addEventListener("DOMContentLoaded", resolve);
    });
}
promiseDOMready().then(initOnLoad);
苏佲洛 2025-02-06 06:38:45

我通常使用的简单通用功能。

const promisify = (fn, ...args) => {
  return new Promise((resolve, reject) => {
    fn(...args, (err, data) => {
      if (err) {
        return reject(err);
      }
      resolve(data);
    });
  });
};

如何使用

  • 函数 prosisify 接受带回调的函数:
   const cb = (result) => `The result is ${result}`;

   const sum = (a, b, cb) => {
    const result = a + b;
    cb(result); // passing args to the callback function
   }


  // using the util
  promise = promisify(sum, 3, 1, cb);
  promise.then(x => console.log(x)) // 4

您可能不是在寻找此答案,但这将有助于了解可用utils的内部工作

A simple generic function I normally use.

const promisify = (fn, ...args) => {
  return new Promise((resolve, reject) => {
    fn(...args, (err, data) => {
      if (err) {
        return reject(err);
      }
      resolve(data);
    });
  });
};

How to use it

  • The function promisify accepts a function with a callback:
   const cb = (result) => `The result is ${result}`;

   const sum = (a, b, cb) => {
    const result = a + b;
    cb(result); // passing args to the callback function
   }


  // using the util
  promise = promisify(sum, 3, 1, cb);
  promise.then(x => console.log(x)) // 4

You are probably not looking for this answer, but this will help understand the inner workings of the available utils

救星 2025-02-06 06:38:45

在node.js 8.0.0的发行候选中,有一个新的实用程序, util.promisify (我已经写了 util.promisify ),它封装了授权任何功能的能力。

它与其他答案中建议的方法没有太大不同,但具有成为核心方法的优势,而不是需要其他依赖性。

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

然后,您是 ReadFile 方法,该方法返回本机 Promise

readFile('./notes.txt')
  .then(txt => console.log(txt))
  .catch(...);

In release candidate for Node.js 8.0.0, there's a new utility, util.promisify (I've written about util.promisify), that encapsulates the capacity of promisifying whatever function.

It is not much different from the approaches suggested in the other answers, but has the advantage of being a core method, and not requiring additional dependencies.

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

Then you've a readFile method that returns a native Promise.

readFile('./notes.txt')
  .then(txt => console.log(txt))
  .catch(...);
救赎№ 2025-02-06 06:38:45

您可以使用节点JS使用JavaScript本机承诺。

我的云9代码链接: https:///////ide.c9.io/adx2803/native - 启示性节点

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
        request.get(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(body);
            }
            else {
                reject(error);
            }
        })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
    //get the post with post id 100
    promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
        var obj = JSON.parse(result);
        return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
    })
    .catch(function (e) {
        console.log(e);
    })
    .then(function (result) {
        res.end(result);
    })
})

var server = app.listen(8081, function () {
    var host = server.address().address
    var port = server.address().port

    console.log("Example app listening at http://%s:%s", host, port)
})

//run webservice on browser : http://localhost:8081/listAlbums

You can use JavaScript native promises with Node JS.

My Cloud 9 code link: https://ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
        request.get(url, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                resolve(body);
            }
            else {
                reject(error);
            }
        })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
    //get the post with post id 100
    promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
        var obj = JSON.parse(result);
        return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
    })
    .catch(function (e) {
        console.log(e);
    })
    .then(function (result) {
        res.end(result);
    })
})

var server = app.listen(8081, function () {
    var host = server.address().address
    var port = server.address().port

    console.log("Example app listening at http://%s:%s", host, port)
})

//run webservice on browser : http://localhost:8081/listAlbums
挥剑断情 2025-02-06 06:38:45

借助普通的旧香草JavaScript,这是一个解决API回调的解决方案。

function get(url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url);
        xhr.addEventListener('readystatechange', function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    console.log('successful ... should call callback ... ');
                    callback(null, JSON.parse(xhr.responseText));
                } else {
                    console.log('error ... callback with error data ... ');
                    callback(xhr, null);
                }
            }
        });
        xhr.send();
    }

/**
     * @function promisify: convert api based callbacks to promises
     * @description takes in a factory function and promisifies it
     * @params {function} input function to promisify
     * @params {array} an array of inputs to the function to be promisified
     * @return {function} promisified function
     * */
    function promisify(fn) {
        return function () {
            var args = Array.prototype.slice.call(arguments);
            return new Promise(function(resolve, reject) {
                fn.apply(null, args.concat(function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
                }));
            });
        }
    }

var get_promisified = promisify(get);
var promise = get_promisified('some_url');
promise.then(function (data) {
        // corresponds to the resolve function
        console.log('successful operation: ', data);
}, function (error) {
        console.log(error);
});

With plain old vanilla javaScript, here's a solution to promisify an api callback.

function get(url, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url);
        xhr.addEventListener('readystatechange', function () {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    console.log('successful ... should call callback ... ');
                    callback(null, JSON.parse(xhr.responseText));
                } else {
                    console.log('error ... callback with error data ... ');
                    callback(xhr, null);
                }
            }
        });
        xhr.send();
    }

/**
     * @function promisify: convert api based callbacks to promises
     * @description takes in a factory function and promisifies it
     * @params {function} input function to promisify
     * @params {array} an array of inputs to the function to be promisified
     * @return {function} promisified function
     * */
    function promisify(fn) {
        return function () {
            var args = Array.prototype.slice.call(arguments);
            return new Promise(function(resolve, reject) {
                fn.apply(null, args.concat(function (err, result) {
                    if (err) reject(err);
                    else resolve(result);
                }));
            });
        }
    }

var get_promisified = promisify(get);
var promise = get_promisified('some_url');
promise.then(function (data) {
        // corresponds to the resolve function
        console.log('successful operation: ', data);
}, function (error) {
        console.log(error);
});
寄居者 2025-02-06 06:38:45

Kriskowal的Q库包括回调对启示功能。
这样的方法:

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

可以用q.ninvoke转换

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

The Q library by kriskowal includes callback-to-promise functions.
A method like this:

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

can be converted with Q.ninvoke

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});
泪是无色的血 2025-02-06 06:38:45

当您有几个功能可以进行回调时,您希望他们返回诺言,您可以使用此功能进行转换。

function callbackToPromise(func){

    return function(){

        // change this to use what ever promise lib you are using
        // In this case i'm using angular $q that I exposed on a util module

        var defered = util.$q.defer();

        var cb = (val) => {
            defered.resolve(val);
        }

        var args = Array.prototype.slice.call(arguments);
        args.push(cb);    
        func.apply(this, args);

        return defered.promise;
    }
}

When you have a few functions that take a callback and you want them to return a promise instead you can use this function to do the conversion.

function callbackToPromise(func){

    return function(){

        // change this to use what ever promise lib you are using
        // In this case i'm using angular $q that I exposed on a util module

        var defered = util.$q.defer();

        var cb = (val) => {
            defered.resolve(val);
        }

        var args = Array.prototype.slice.call(arguments);
        args.push(cb);    
        func.apply(this, args);

        return defered.promise;
    }
}
屋檐 2025-02-06 06:38:45

在Node v7.6+下,已内置的诺言和异步:

// promisify.js
let promisify = fn => (...args) =>
    new Promise((resolve, reject) =>
        fn(...args, (err, result) => {
            if (err) return reject(err);
            return resolve(result);
        })
    );

module.exports = promisify;

如何使用:

let readdir = require('fs').readdir;
let promisify = require('./promisify');
let readdirP = promisify(readdir);

async function myAsyncFn(path) {
    let entries = await readdirP(path);
    return entries;
}

Under node v7.6+ which has built in promises and async:

// promisify.js
let promisify = fn => (...args) =>
    new Promise((resolve, reject) =>
        fn(...args, (err, result) => {
            if (err) return reject(err);
            return resolve(result);
        })
    );

module.exports = promisify;

How to use:

let readdir = require('fs').readdir;
let promisify = require('./promisify');
let readdirP = promisify(readdir);

async function myAsyncFn(path) {
    let entries = await readdirP(path);
    return entries;
}
不念旧人 2025-02-06 06:38:45

在node.js 8中,您可以使用此NPM模块 对象方法 使用此npm模块:

https://www.npmjs.com/package/doasync

它使用 util.promisify proxies 不变。 回忆也可以使用弱图的使用来完成。以下是一些示例:

带有对象:

const fs = require('fs');
const doAsync = require('doasync');

doAsync(fs).readFile('package.json', 'utf8')
  .then(result => {
    console.dir(JSON.parse(result), {colors: true});
  });

带有函数:

doAsync(request)('http://www.google.com')
  .then(({body}) => {
    console.log(body);
    // ...
  });

您甚至可以使用本机呼叫应用来绑定某些上下文:

doAsync(myFunc).apply(context, params)
  .then(result => { /*...*/ });

In Node.js 8 you can promisify object methods on the fly using this npm module:

https://www.npmjs.com/package/doasync

It uses util.promisify and Proxies so that your objects stay unchanged. Memoization is also done with the use of WeakMaps). Here are some examples:

With objects:

const fs = require('fs');
const doAsync = require('doasync');

doAsync(fs).readFile('package.json', 'utf8')
  .then(result => {
    console.dir(JSON.parse(result), {colors: true});
  });

With functions:

doAsync(request)('http://www.google.com')
  .then(({body}) => {
    console.log(body);
    // ...
  });

You can even use native call and apply to bind some context:

doAsync(myFunc).apply(context, params)
  .then(result => { /*...*/ });
2025-02-06 06:38:45

您可以在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
    });

}

在此典范中,承诺没有理由失败,因此 recond> recond> recond()从未被调用。

You can use native Promise in ES6, for exemple dealing with 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
    });

}

In this exemple, the Promise has no reason to fail, so reject() is never called.

习惯那些不曾习惯的习惯 2025-02-06 06:38:45

ES6-启示录将基于回调的功能转换为基于承诺的功能。

const promisify = require('es6-promisify');

const promisedFn = promisify(callbackedFn, args);

参考: https://www.npmjs.com/package/package/es6-promisify

es6-promisify converts callback-based functions to Promise-based functions.

const promisify = require('es6-promisify');

const promisedFn = promisify(callbackedFn, args);

Ref: https://www.npmjs.com/package/es6-promisify

雨落星ぅ辰 2025-02-06 06:38:45

您可以做这样的事情

// @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)
}

You can do something like this

// @flow

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

export default toPromise

Then use it

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

  console.log(friends)
}
嘿看小鸭子会跑 2025-02-06 06:38:45

回调样式函数始终像这样(Node.js中的几乎所有函数都是此样式):

//fs.readdir(path[, options], callback)
fs.readdir('mypath',(err,files)=>console.log(files))

此样式具有相同的功能:

  1. 回调函数通过最后一个参数传递。

  2. 回调函数始终接受错误对象作为第一个参数。

因此,您可以编写一个函数,以转换这样的函数:

const R =require('ramda')

/**
 * A convenient function for handle error in callback function.
 * Accept two function res(resolve) and rej(reject) ,
 * return a wrap function that accept a list arguments,
 * the first argument as error, if error is null,
 * the res function will call,else the rej function.
 * @param {function} res the function which will call when no error throw
 * @param {function} rej the function which will call when  error occur
 * @return {function} return a function that accept a list arguments,
 * the first argument as error, if error is null, the res function
 * will call,else the rej function
 **/
const checkErr = (res, rej) => (err, ...data) => R.ifElse(
    R.propEq('err', null),
    R.compose(
        res,
        R.prop('data')
    ),
    R.compose(
        rej,
        R.prop('err')
    )
)({err, data})

/**
 * wrap the callback style function to Promise style function,
 * the callback style function must restrict by convention:
 * 1. the function must put the callback function where the last of arguments,
 * such as (arg1,arg2,arg3,arg...,callback)
 * 2. the callback function must call as callback(err,arg1,arg2,arg...)
 * @param {function} fun the callback style function to transform
 * @return {function} return the new function that will return a Promise,
 * while the origin function throw a error, the Promise will be Promise.reject(error),
 * while the origin function work fine, the Promise will be Promise.resolve(args: array),
 * the args is which callback function accept
 * */
 const toPromise = (fun) => (...args) => new Promise(
    (res, rej) => R.apply(
        fun,
        R.append(
            checkErr(res, rej),
            args
        )
    )
)

对于更简洁的示例,示例使用了ramda.js。 Ramda.js是功能编程的绝佳库。在上面的代码中,我们使用的是应用(例如javascript function.prototype.apply )和附加(例如javascript function.prototype.prototype.push.push )。
因此,我们现在可以将回调样式函数转换为Prome Style函数:

const {readdir} = require('fs')
const readdirP = toPromise(readdir)
readdir(Path)
    .then(
        (files) => console.log(files),
        (err) => console.log(err)
    )

topromise checkerr 函数是 berserk 库,这是 ramda.js 的功能编程库叉(由我创建)。

希望这个答案对您有用。

The callback style function always like this(almost all function in node.js is this style):

//fs.readdir(path[, options], callback)
fs.readdir('mypath',(err,files)=>console.log(files))

This style has same feature:

  1. the callback function is passed by last argument.

  2. the callback function always accept the error object as it's first argument.

So, you could write a function for convert a function with this style like this:

const R =require('ramda')

/**
 * A convenient function for handle error in callback function.
 * Accept two function res(resolve) and rej(reject) ,
 * return a wrap function that accept a list arguments,
 * the first argument as error, if error is null,
 * the res function will call,else the rej function.
 * @param {function} res the function which will call when no error throw
 * @param {function} rej the function which will call when  error occur
 * @return {function} return a function that accept a list arguments,
 * the first argument as error, if error is null, the res function
 * will call,else the rej function
 **/
const checkErr = (res, rej) => (err, ...data) => R.ifElse(
    R.propEq('err', null),
    R.compose(
        res,
        R.prop('data')
    ),
    R.compose(
        rej,
        R.prop('err')
    )
)({err, data})

/**
 * wrap the callback style function to Promise style function,
 * the callback style function must restrict by convention:
 * 1. the function must put the callback function where the last of arguments,
 * such as (arg1,arg2,arg3,arg...,callback)
 * 2. the callback function must call as callback(err,arg1,arg2,arg...)
 * @param {function} fun the callback style function to transform
 * @return {function} return the new function that will return a Promise,
 * while the origin function throw a error, the Promise will be Promise.reject(error),
 * while the origin function work fine, the Promise will be Promise.resolve(args: array),
 * the args is which callback function accept
 * */
 const toPromise = (fun) => (...args) => new Promise(
    (res, rej) => R.apply(
        fun,
        R.append(
            checkErr(res, rej),
            args
        )
    )
)

For more concise, above example used ramda.js. Ramda.js is a excellent library for functional programming. In above code, we used it's apply(like javascript function.prototype.apply) and append(like javascript function.prototype.push ).
So, we could convert the a callback style function to promise style function now:

const {readdir} = require('fs')
const readdirP = toPromise(readdir)
readdir(Path)
    .then(
        (files) => console.log(files),
        (err) => console.log(err)
    )

toPromise and checkErr function is own by berserk library, it's a functional programming library fork by ramda.js(create by me).

Hope this answer is useful for you.

半城柳色半声笛 2025-02-06 06:38:45

回调函数的委托版本是 p 函数:

var P = function() {
  var self = this;
  var method = arguments[0];
  var params = Array.prototype.slice.call(arguments, 1);
  return new Promise((resolve, reject) => {
    if (method && typeof(method) == 'function') {
      params.push(function(err, state) {
        if (!err) return resolve(state)
        else return reject(err);
      });
      method.apply(self, params);
    } else return reject(new Error('not a function'));
  });
}
var callback = function(par, callback) {
  var rnd = Math.floor(Math.random() * 2) + 1;
  return rnd > 1 ? callback(null, par) : callback(new Error("trap"));
}

callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))

P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))

p 函数要求回调签名必须为回调(错误,结果)

My promisify version of a callback function is the P function:

var P = function() {
  var self = this;
  var method = arguments[0];
  var params = Array.prototype.slice.call(arguments, 1);
  return new Promise((resolve, reject) => {
    if (method && typeof(method) == 'function') {
      params.push(function(err, state) {
        if (!err) return resolve(state)
        else return reject(err);
      });
      method.apply(self, params);
    } else return reject(new Error('not a function'));
  });
}
var callback = function(par, callback) {
  var rnd = Math.floor(Math.random() * 2) + 1;
  return rnd > 1 ? callback(null, par) : callback(new Error("trap"));
}

callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))
callback("callback", (err, state) => err ? console.error(err) : console.log(state))

P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))
P(callback, "promise").then(v => console.log(v)).catch(e => console.error(e))

The P function requires that the callback signature must be callback(error,result).

-柠檬树下少年和吉他 2025-02-06 06:38:45

以下是如何将函数(回调API)转换为承诺的实现。

function promisify(functionToExec) {
  return function() {
    var array = Object.values(arguments);
    return new Promise((resolve, reject) => {
      array.push(resolve)
      try {
         functionToExec.apply(null, array);
      } catch (error) {
         reject(error)
      }
    })
  }
}

// USE SCENARIO

function apiFunction (path, callback) { // Not a promise
  // Logic
}

var promisedFunction = promisify(apiFunction);

promisedFunction('path').then(()=>{
  // Receive the result here (callback)
})

// Or use it with await like this
let result = await promisedFunction('path');

Below is the implementation of how a function (callback API) can be converted to a promise.

function promisify(functionToExec) {
  return function() {
    var array = Object.values(arguments);
    return new Promise((resolve, reject) => {
      array.push(resolve)
      try {
         functionToExec.apply(null, array);
      } catch (error) {
         reject(error)
      }
    })
  }
}

// USE SCENARIO

function apiFunction (path, callback) { // Not a promise
  // Logic
}

var promisedFunction = promisify(apiFunction);

promisedFunction('path').then(()=>{
  // Receive the result here (callback)
})

// Or use it with await like this
let result = await promisedFunction('path');

死开点丶别碍眼 2025-02-06 06:38:45

承诺始终具有 Resolve 拒绝。当您编写异步包装器时,只需调用分辨率,然后就可以了。

您可以为几乎任何功能编写包装函数,以便进行回调这样的功能:

const myAsyncWrapper = (...params) =>
  new Promise((resolve, reject) => 
    someFunctionWithCallback(...params, (error, response) =>
      error ? reject(error) : resolve(response)
    )
  );

您可以进一步将回调的转换功能写入承诺:

const promisify =
  (functionWithCallback) =>
  (...params) =>
    new Promise((resolve, reject) =>
      functionWithCallback(...params, (error, response) =>
        error ? reject(error) : resolve(response)
      )
    );

当使用较旧的库或SDK时,包装器功能的概念尤其有用。例如,考虑Facebook Graph API的JavaScript SDK,该JavaScript SDK使用类似的回调结构来制作API请求。

FB.api(apiURL, options, function (request) {
  if (request.error || !request) return;
  // handle request
});

在现代应用程序中,使用基于承诺的API要有用得多。
如果您仅使用一次或两次函数,则最好单独诺言:

// in an async function
const response = await new Promise((resolve, reject) =>
  FB.api(apiURL, (res) => (res?.error ? reject(res?.error) : resolve(res)))
);

如果您经常使用该函数,则可以使用相同的包装器概念来编写这样的函数:

const apiWrapper = (...params) =>
  new Promise((resolve, reject) => 
    FB.api(...params, (res) => (res?.error ? reject(res?.error) : resolve(res)))
  );

尽管有时候有时会很棒,但他们会赢对于这样的特定实例。在这样的时代,请在Github上查找现代包装纸,或这样写自己的包装。

Promises always have a resolve and a reject. When you write an async wrapper, just call the resolve and there you go.

You can write a wrapper function for pretty much any function taking a callback like so:

const myAsyncWrapper = (...params) =>
  new Promise((resolve, reject) => 
    someFunctionWithCallback(...params, (error, response) =>
      error ? reject(error) : resolve(response)
    )
  );

You can take this further to write a conversion function of callbacks to promises:

const promisify =
  (functionWithCallback) =>
  (...params) =>
    new Promise((resolve, reject) =>
      functionWithCallback(...params, (error, response) =>
        error ? reject(error) : resolve(response)
      )
    );

This concept of wrapper functions is especially useful when using older libraries or SDKs. For example, consider the Facebook Graph API's JavaScript SDK, which uses a similar callback structure for making API requests.

FB.api(apiURL, options, function (request) {
  if (request.error || !request) return;
  // handle request
});

In modern applications, it is much more useful to use a promise-based API.
If you use a function only once or twice, it may be better to promisify the response individually:

// in an async function
const response = await new Promise((resolve, reject) =>
  FB.api(apiURL, (res) => (res?.error ? reject(res?.error) : resolve(res)))
);

If you use the function a lot, you can use the same wrapper concept to write a function like so:

const apiWrapper = (...params) =>
  new Promise((resolve, reject) => 
    FB.api(...params, (res) => (res?.error ? reject(res?.error) : resolve(res)))
  );

Although promisifiers are great sometimes, they won't work for specific instances like this. In times like these, look on Github for a modern wrapper, or write your own like this.

遗忘曾经 2025-02-06 06:38:45

也许已经回答了,但这是我通常这样做的:

// given you've defined this `Future` fn somewhere:
const Future = fn => {return new Promise((r,t) => fn(r,t))}

// define an eventFn that takes a promise `resolver`
const eventFn = resolve => {
  // do event related closure actions here. When finally done, call `resolve()`
  something.oneventfired = e => {resolve(e)}
}

// invoke eventFn in an `async` workflowFn using `Future`
// to obtain a `promise` wrapper
const workflowFn = async () => {await Future(eventFn)}

特别适用于 indexeddb 事件包装器以简化用法。

或者,您可能会发现 Future 的这种变化是更通用的

class PromiseEx extends Promise {
  resolve(v,...a) {
    this.settled = true; this.settledValue = v;
    return(this.resolve_(v,...a))
  }
  reject(v,...a) {
    this.settled = false; this.settledValue = v;
    return(this.reject_(v,...a))
  }
  static Future(fn,...args) {
    let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
    ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
    return(ft)
  }
}

Perhaps already answered, but this is how I do it typically:

// given you've defined this `Future` fn somewhere:
const Future = fn => {return new Promise((r,t) => fn(r,t))}

// define an eventFn that takes a promise `resolver`
const eventFn = resolve => {
  // do event related closure actions here. When finally done, call `resolve()`
  something.oneventfired = e => {resolve(e)}
}

// invoke eventFn in an `async` workflowFn using `Future`
// to obtain a `promise` wrapper
const workflowFn = async () => {await Future(eventFn)}

Especially for things like indexedDb event wrappers to simplify usage.

Or you might find this variation of Future to be more general purpose

class PromiseEx extends Promise {
  resolve(v,...a) {
    this.settled = true; this.settledValue = v;
    return(this.resolve_(v,...a))
  }
  reject(v,...a) {
    this.settled = false; this.settledValue = v;
    return(this.reject_(v,...a))
  }
  static Future(fn,...args) {
    let r,t,ft = new PromiseEx((r_,t_) => {r=r_;t=t_})
    ft.resolve_ = r; ft.reject_ = t; fn(ft,...args);
    return(ft)
  }
}
变身佩奇 2025-02-06 06:38:45

坏死有点 noreflow noreferrer


“在此答案结束时查看摘要示例


写入/转换函数,可以称为

cb(错误,结果)或或 new Promise(...)格式


  • PromisetoCB 转换并导出了先前已编码的现有函数,该功能返回了Promise
  • cbtopromise 转换并导出以前编码的现有函数,该函数以前被编码为最后一个参数(错误,结果,结果,结果) )
    • 如果包装功能提供超过1个结果,则结果将是结果
    • eg cb(未定义,路径,stat) ---&gt; resolve([Path,stat])/ cb(undefined,[path,stat])
  • aspromise 允许您代码一个新功能以返回承诺,但可以将其称为
  • 一个新功能以调用 cb(err,结果)

ascallback 允许您编码 进行2个参数,并根据随机数解决/拒绝/错误。

ARG2也可用于强迫通过或失败。 (寻找“ -pass”或“ -fail”)。

包装现有函数

  • 将功能导出到当前“ this”(或使用 promisetocb(函数myfunc(){},newthis);


    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    

或代码新功能(嵌入包装器)。

     function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}

测试上述功能的SCIPT


    const local = {}; 
    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    
    function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    const log=console.log.bind(console),info=console.info.bind(console),error=console.error.bind(console);
    
    sampleFunc1("sample1","promise").then (log).catch(error);
    local.sampleFunc2("sample2","promise").then (log).catch(error);
    sampleFunc3("sample3","promise").then (log).catch(error);
    sampleFunc4("sample4","promise").then (log).catch(error);

    sampleFunc1("sample1","callback",info);
    local.sampleFunc2("sample2","callback",info);
    sampleFunc3("sample3","callback",info);
    sampleFunc4("sample4","callback",info);
    
    sampleFunc1("sample1","promise-pass").then (log).catch(error);
    local.sampleFunc2("sample2","promise-pass").then (log).catch(error);
    sampleFunc3("sample3","promise-pass").then (log).catch(error);
    sampleFunc4("sample4","promise-pass").then (log).catch(error);

    sampleFunc1("sample1","callback-pass",info);
    local.sampleFunc2("sample2","callback-pass",info);
    sampleFunc3("sample3","callback-pass",info);
    sampleFunc4("sample4","callback-pass",info);
    
    
    sampleFunc1("sample1","promise-fail").then (log).catch(error);
    local.sampleFunc2("sample2","promise-fail").then (log).catch(error);
    sampleFunc3("sample3","promise-fail").then (log).catch(error);
    sampleFunc4("sample4","promise-fail").then (log).catch(error);
    
    sampleFunc1("sample1","callback-fail",info);
    local.sampleFunc2("sample2","callback-fail",info);
    sampleFunc3("sample3","callback-fail",info);
    sampleFunc4("sample4","callback-fail",info);
 

    var cpArgs = Array.prototype.slice.call.bind(Array.prototype.slice);

    function promiseToCB (nm,fn,THIS) {
        if (typeof nm==='function') {
            THIS=fn;fn=nm;nm=fn.name;
        }
        THIS=THIS||this;
        const func = function () {
           let args = cpArgs(arguments);
            if (typeof args[args.length-1]==='function') {
                const cb = args.pop();
                return fn.apply(THIS,args).then(function(r){
                   cb (undefined,r);
                }).catch(cb);  
            } else {
                return fn.apply(THIS,args);
            }
        };
        Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
        if (THIS[nm]) delete THIS[nm];
        Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
        return func;
    }

    function cbToPromise (nm,fn,THIS) {
        if (typeof nm==='function') {
            THIS=fn;fn=nm;nm=fn.name;
        }
        THIS=THIS||this;
        const func = function () {
           let args = cpArgs(arguments);
            if (typeof args[args.length-1]==='function') {
                return fn.apply(THIS,args);
            } else {
                return new Promise(function(resolve,reject){
                    
                    args.push(function(err,result){
                          if (err) return reject(err);
                          if (arguments.length==2) {
                             return resolve(result);
                          }
                          return resolve(cpArgs(arguments,1));
                    });
                              
                    fn.apply(THIS,args);
                    
                });
            }
        };
        Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
        if (THIS[nm]) delete THIS[nm];
        Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
        return func;

    }

    function asPromise (args,resolver,no_err) {
        const cb = args[args.length-1],
        promise  = new Promise(resolver);
        return (typeof cb==='function')  ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
    }

    function asCallback (args,wrap,no_err) {
        const cb = args[args.length-1],
        promise=new Promise(function resolver(resolve,reject) {
            return wrap (function (err,result) {
                 if (err) return reject(err);
                 resolve(result);
            });
        });
        return (typeof cb==='function')  ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
    }


    function cbPromiseTest(){
        /*global sampleFunc1,sampleFunc2*/
        
        const local = {}; 
        promiseToCB(function sampleFunc1(arg1,arg2) {
            console.log("deciding:",arg1,arg2);
            return new Promise(function(resolve,reject){
           
               const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
               
               setTimeout(function(){
                   if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
        
                       console.log("complete:",arg1,arg2);
                       clearTimeout(timer);
                       resolve([arg1,arg2,"all good"].join("-"));
                   }
               },2000);
            
            });
        });
        
        cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   cb(undefined,[arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        },local);
        
        function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        });}
        
        function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   cb(undefined,[arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        });}
        
        const log=console.log.bind(console),info=console.info.bind(console),error=console.error.bind(console);
        
        sampleFunc1("sample1","promise").then (log).catch(error);
        local.sampleFunc2("sample2","promise").then (log).catch(error);
        sampleFunc3("sample3","promise").then (log).catch(error);
        sampleFunc4("sample4","promise").then (log).catch(error);

        sampleFunc1("sample1","callback",info);
        local.sampleFunc2("sample2","callback",info);
        sampleFunc3("sample3","callback",info);
        sampleFunc4("sample4","callback",info);
        
        sampleFunc1("sample1","promise-pass").then (log).catch(error);
        local.sampleFunc2("sample2","promise-pass").then (log).catch(error);
        sampleFunc3("sample3","promise-pass").then (log).catch(error);
        sampleFunc4("sample4","promise-pass").then (log).catch(error);

        sampleFunc1("sample1","callback-pass",info);
        local.sampleFunc2("sample2","callback-pass",info);
        sampleFunc3("sample3","callback-pass",info);
        sampleFunc4("sample4","callback-pass",info);
        
        
        sampleFunc1("sample1","promise-fail").then (log).catch(error);
        local.sampleFunc2("sample2","promise-fail").then (log).catch(error);
        sampleFunc3("sample3","promise-fail").then (log).catch(error);
        sampleFunc4("sample4","promise-fail").then (log).catch(error);
        
        sampleFunc1("sample1","callback-fail",info);
        local.sampleFunc2("sample2","callback-fail",info);
        sampleFunc3("sample3","callback-fail",info);
        sampleFunc4("sample4","callback-fail",info);
     
    }
    cbPromiseTest();

Necromancing a little, bit this link may be useful....


TLDR; look at the snippet example at the end of this answer


write/convert functions that can be called expecting

a cb(error,result) or new Promise (...) format


  • promiseToCB converts and exports an existing function that's been previously coded to return a promise
  • cbToPromise converts and exports an existing function that's been previously coded to call the last argument with (error,result)
    • if wrapped function supplies more than 1 result, the result will be an array of results
    • eg cb(undefined,path,stat) ---> resolve([path,stat]) / cb(undefined,[path,stat])
  • asPromise lets you code a new function to return a promise, but it can be called either way
  • asCallback lets you code a new function to call cb(err,result), but it can be invoked either way

sample functions

each sample takes 2 arguments, and resolves/rejects/errors based on random number.

arg2 can be also be used to force pass or fail. (looks for "-pass" or "-fail").

wrap existing functions

  • exports the function to current "this" (or use promiseToCB(function myFunc(){},newThis); )


    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    

or code new functions, which embed a wrapper.

     function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}

test scipt for above functions


    const local = {}; 
    promiseToCB(function sampleFunc1(arg1,arg2) {
        console.log("deciding:",arg1,arg2);
        return new Promise(function(resolve,reject){
       
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
    
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
        
        });
    });
    
    cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    },local);
    
    function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               resolve([arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
       console.log("deciding:",arg1,arg2);
       const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
       
       setTimeout(function(){
           if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
               console.log("complete:",arg1,arg2);
               clearTimeout(timer);
               cb(undefined,[arg1,arg2,"all good"].join("-"));
           }
       },2000);
        
    });}
    
    const log=console.log.bind(console),info=console.info.bind(console),error=console.error.bind(console);
    
    sampleFunc1("sample1","promise").then (log).catch(error);
    local.sampleFunc2("sample2","promise").then (log).catch(error);
    sampleFunc3("sample3","promise").then (log).catch(error);
    sampleFunc4("sample4","promise").then (log).catch(error);

    sampleFunc1("sample1","callback",info);
    local.sampleFunc2("sample2","callback",info);
    sampleFunc3("sample3","callback",info);
    sampleFunc4("sample4","callback",info);
    
    sampleFunc1("sample1","promise-pass").then (log).catch(error);
    local.sampleFunc2("sample2","promise-pass").then (log).catch(error);
    sampleFunc3("sample3","promise-pass").then (log).catch(error);
    sampleFunc4("sample4","promise-pass").then (log).catch(error);

    sampleFunc1("sample1","callback-pass",info);
    local.sampleFunc2("sample2","callback-pass",info);
    sampleFunc3("sample3","callback-pass",info);
    sampleFunc4("sample4","callback-pass",info);
    
    
    sampleFunc1("sample1","promise-fail").then (log).catch(error);
    local.sampleFunc2("sample2","promise-fail").then (log).catch(error);
    sampleFunc3("sample3","promise-fail").then (log).catch(error);
    sampleFunc4("sample4","promise-fail").then (log).catch(error);
    
    sampleFunc1("sample1","callback-fail",info);
    local.sampleFunc2("sample2","callback-fail",info);
    sampleFunc3("sample3","callback-fail",info);
    sampleFunc4("sample4","callback-fail",info);
 

    var cpArgs = Array.prototype.slice.call.bind(Array.prototype.slice);

    function promiseToCB (nm,fn,THIS) {
        if (typeof nm==='function') {
            THIS=fn;fn=nm;nm=fn.name;
        }
        THIS=THIS||this;
        const func = function () {
           let args = cpArgs(arguments);
            if (typeof args[args.length-1]==='function') {
                const cb = args.pop();
                return fn.apply(THIS,args).then(function(r){
                   cb (undefined,r);
                }).catch(cb);  
            } else {
                return fn.apply(THIS,args);
            }
        };
        Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
        if (THIS[nm]) delete THIS[nm];
        Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
        return func;
    }

    function cbToPromise (nm,fn,THIS) {
        if (typeof nm==='function') {
            THIS=fn;fn=nm;nm=fn.name;
        }
        THIS=THIS||this;
        const func = function () {
           let args = cpArgs(arguments);
            if (typeof args[args.length-1]==='function') {
                return fn.apply(THIS,args);
            } else {
                return new Promise(function(resolve,reject){
                    
                    args.push(function(err,result){
                          if (err) return reject(err);
                          if (arguments.length==2) {
                             return resolve(result);
                          }
                          return resolve(cpArgs(arguments,1));
                    });
                              
                    fn.apply(THIS,args);
                    
                });
            }
        };
        Object.defineProperty(func,'name',{value:nm,enumerable:false,configurable: true});
        if (THIS[nm]) delete THIS[nm];
        Object.defineProperty(THIS,nm,{value:func,enumerable:false,configurable: true});
        return func;

    }

    function asPromise (args,resolver,no_err) {
        const cb = args[args.length-1],
        promise  = new Promise(resolver);
        return (typeof cb==='function')  ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
    }

    function asCallback (args,wrap,no_err) {
        const cb = args[args.length-1],
        promise=new Promise(function resolver(resolve,reject) {
            return wrap (function (err,result) {
                 if (err) return reject(err);
                 resolve(result);
            });
        });
        return (typeof cb==='function')  ? promise.then(function(result){return cb(no_err,result)}).catch(cb) : promise;
    }


    function cbPromiseTest(){
        /*global sampleFunc1,sampleFunc2*/
        
        const local = {}; 
        promiseToCB(function sampleFunc1(arg1,arg2) {
            console.log("deciding:",arg1,arg2);
            return new Promise(function(resolve,reject){
           
               const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
               
               setTimeout(function(){
                   if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
        
                       console.log("complete:",arg1,arg2);
                       clearTimeout(timer);
                       resolve([arg1,arg2,"all good"].join("-"));
                   }
               },2000);
            
            });
        });
        
        cbToPromise('sampleFunc2',function someOtherName(arg1,arg2,cb) {
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   cb(undefined,[arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        },local);
        
        function sampleFunc3(arg1,arg2) {return asPromise(arguments,function(resolve,reject){
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){reject([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   resolve([arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        });}
        
        function sampleFunc4(arg1,arg2) {return asCallback(arguments,function(cb){
           console.log("deciding:",arg1,arg2);
           const timer = setTimeout(function(){cb([arg1,arg2,"ouch"].join("-"));},5000);
           
           setTimeout(function(){
               if (arg2.endsWith("-pass") || (!arg2.endsWith("-fail") && Math.random()<0.5)) {
                   console.log("complete:",arg1,arg2);
                   clearTimeout(timer);
                   cb(undefined,[arg1,arg2,"all good"].join("-"));
               }
           },2000);
            
        });}
        
        const log=console.log.bind(console),info=console.info.bind(console),error=console.error.bind(console);
        
        sampleFunc1("sample1","promise").then (log).catch(error);
        local.sampleFunc2("sample2","promise").then (log).catch(error);
        sampleFunc3("sample3","promise").then (log).catch(error);
        sampleFunc4("sample4","promise").then (log).catch(error);

        sampleFunc1("sample1","callback",info);
        local.sampleFunc2("sample2","callback",info);
        sampleFunc3("sample3","callback",info);
        sampleFunc4("sample4","callback",info);
        
        sampleFunc1("sample1","promise-pass").then (log).catch(error);
        local.sampleFunc2("sample2","promise-pass").then (log).catch(error);
        sampleFunc3("sample3","promise-pass").then (log).catch(error);
        sampleFunc4("sample4","promise-pass").then (log).catch(error);

        sampleFunc1("sample1","callback-pass",info);
        local.sampleFunc2("sample2","callback-pass",info);
        sampleFunc3("sample3","callback-pass",info);
        sampleFunc4("sample4","callback-pass",info);
        
        
        sampleFunc1("sample1","promise-fail").then (log).catch(error);
        local.sampleFunc2("sample2","promise-fail").then (log).catch(error);
        sampleFunc3("sample3","promise-fail").then (log).catch(error);
        sampleFunc4("sample4","promise-fail").then (log).catch(error);
        
        sampleFunc1("sample1","callback-fail",info);
        local.sampleFunc2("sample2","callback-fail",info);
        sampleFunc3("sample3","callback-fail",info);
        sampleFunc4("sample4","callback-fail",info);
     
    }
    cbPromiseTest();

沩ん囻菔务 2025-02-06 06:38:45

由于我们知道预先基于回调的功能的特征,因此
我们可以创建一个转换基于回调功能的函数
归还承诺的等效功能。

  • 回调是函数的最后一个参数

  • 的最后一个参数,如果有错误,它始终将第一个参数传递给回调

  • 错误之后的任何返回值将传递给回调

     函数promisify(yourcallbackapi){
        返回函数promissived(... args){
          返回新的承诺((分辨,拒绝)=&gt; {
            // newargs = [.. args,回调]
            const newargs = [
              ... args,
              函数(err,结果){
                如果(err){
                  返回拒绝(err);
                }
                解析(结果);
              },,
            ];
            //与新参数列表一起调用您的callbackapi
            YourCallBackapi(... Newargs);
          });
        };
      }
     

since we know the characteristics of a callback-based function in advance,
we can create a function that transforms a callback-based function
into an equivalent function returning a Promise.

  • The callback is the last argument of the function

  • If there is an error, it always the first argument passed to the callback

  • Any return value is passed after the error to the callback

     function promisify(yourCallbackApi) {
        return function promisified(...args) {
          return new Promise((resolve, reject) => {
            // newArgs=[..args,callback]
            const newArgs = [
              ...args,
              function (err, result) {
                if (err) {
                  return reject(err);
                }
                resolve(result);
              },
            ];
            // invoke yourCallbackApi with the new list of arguments
            yourCallbackApi(...newArgs);
          });
        };
      }
    
南…巷孤猫 2025-02-06 06:38:45

大约迟到了5年,但是我想在这里发布我的Promesify版本,该版本从回调API中获取功能,并将其变成承诺,

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

请在此处查看此非常简单的版本:

It is like 5 years late, but I wanted to post here my promesify version which takes functions from callbacks API and turns them into promises

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

Take a look to this very simple version here:
https://gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文