如何从图书馆创建承诺

时间:2017-08-03 20:40:48

标签: javascript promise

我对此感到困惑,因为到目前为止我找到的每个教程都假定我可以编辑库代码,或者库只有回调或者回调作为最后一个参数。

我正在使用的库具有各种功能设置 using Dijkstra.NET.Contract; using Dijkstra.NET.Model; using Dijkstra.NET.ShortestPath; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; namespace Test.Polygon { class Program { static void Main(string[] args) { var points = new List<Point> { new Point(210, 540), new Point(330, 420), new Point(360, 420), new Point(420, 390), new Point(450, 330), new Point(480, 315), new Point(510, 270), new Point(570, 240), new Point(630, 240), new Point(690, 180), new Point(750, 150), new Point(810, 120), new Point(864, 120), new Point(864, 60), new Point(810, 60), new Point(750, 90), new Point(690, 120), new Point(630, 150), new Point(570, 150), new Point(510, 210), new Point(480, 255), new Point(450, 270), new Point(420, 330), new Point(360, 360), new Point(330, 360), new Point(156, 480) }; var start = new Point(190, 500); var target = new Point(840, 80); var image = new Bitmap(1000, 600); using (var graphics = Graphics.FromImage(image)) { graphics.Clear(Color.White); graphics.FillPie(Brushes.Blue, 190, 500, 10, 10, 0, 360); graphics.FillPie(Brushes.Red, 840, 80, 10, 10, 0, 360); graphics.DrawPolygon(new Pen(Color.Black, 2), points.ToArray()); } var path = new GraphicsPath(FillMode.Winding); path.AddPolygon(points.ToArray()); var pointsForConnect = DrawRaster(5, image, path); var dictionary = new Dictionary<uint, Point>(); dictionary.Add(0, start); dictionary.Add(1, target); var graph = new Graph<int, string>(); var i = 2; foreach (var point in pointsForConnect) { dictionary.Add((uint)i, point); graph.AddNode(i); i++; } foreach (var point in dictionary) { foreach (var point2 in dictionary) { if (point.Equals(point2)) { continue; } double dist = Math.Sqrt(Math.Pow(point2.Value.X - point.Value.X, 2) + Math.Pow(point2.Value.Y - point.Value.Y, 2)); if (dist > 50) { continue; } graph.Connect(point.Key, point2.Key, (int)dist, null); //graph.Connect() } } var dijkstra = new Dijkstra<int, string>(graph); IShortestPathResult result = dijkstra.Process(0, 1); //result contains the shortest path var shortestRouteIds = result.GetPath(); var shortestRoutePoints = new List<Point>(); foreach(var x in shortestRouteIds) { shortestRoutePoints.Add(dictionary[x]); } DrawDriver(shortestRoutePoints, image); image.Save("example.bmp"); } private static void DrawDriver(List<Point> points, Bitmap image) { var pen = new Pen(Color.LightGreen, 5); for (var i = 0; i < points.Count - 1; i++) { var x = points[i].X; var y = points[i].Y; var x1 = points[i + 1].X; var y1 = points[i + 1].Y; DrawLineInt(image, new Point(x, y), new Point(x1, y1), pen); } } private static void DrawLineInt(Bitmap bmp, Point p1, Point p2, Pen pen) { using (var graphics = Graphics.FromImage(bmp)) { graphics.DrawLine(pen, p1.X, p1.Y, p2.X, p2.Y); } } private static List<Point> DrawRaster(int edge, Bitmap image, GraphicsPath path) { var points = new List<Point>(); var countHorizontal = image.Width / edge; var countVertical = image.Height / edge; using (var graphics = Graphics.FromImage(image)) { for (int x = 0; x < countHorizontal; x++) { for (int y = 0; y < countVertical; y++) { var boxX = (x * edge) + (edge / 2); var boxY = (y * edge) + (edge / 2); if (!path.IsVisible(boxX, boxY)) { continue; } points.Add(new Point(boxX, boxY)); graphics.DrawRectangle(Pens.LightGray, x * edge, y * edge, edge, edge); } } } return points; } } }

所以在每个实例中,我最终都使用像

这样的代码
function(successCallBack(result), FailCallBack(error),options)

当我只能控制通话,成功和失败时,如何将这些转换为承诺呢?

另外,作为奖励,链条正在访问它们之外的变量。

var options={stuff1:1, stuff2:2};

doStuff(success,failure,options);

function success(result){
    //handle, usually with another call to a similar function, chaining callbacks together
};

function failure(error){
     //handle error
};

由于

2 个答案:

答案 0 :(得分:6)

您可以使用以下功能。它接受promisify和options的函数,并返回promise:

find . -type f -exec perl -p -i -e "s/## Example[^]+### Response/$&New/g" {} \;

可以按如下方式使用:

let promisify = (fn, opts) => {
  return new Promise((resolve, reject) => {
    fn(resolve, reject, opts);
  });
}

答案 1 :(得分:2)

不是每次想要使用函数时都调用promisify,而是可以包装一次并获得一个可以根据需要使用的新函数。新函数将返回一个promise并解决/拒绝而不是成功和失败的回调。此特定版本的promisify专门针对您显示fn(successCallback, errorCallback, options)的调用约定进行编码。如果您有其他具有不同调用约定的函数,则可以为它们创建不同的promisify版本:

// return a promisified function replacement for this specific
//    calling convention: fn(successCallback, errorCallback, options)
function promisify1(fn) {
    return function(options) {
        return new Promise((resolve, reject) => {
            fn(resolve, reject, options);
        });
    }
}

那么,你会像这样使用它:

// do this once, somewhere near where doStuff is imported
let doStuffPromise = promisify1(doStuff);

// then, anytime you would normally use doStuff(), you can just use
//    doStuffPromise() instead

doStuffPromise(options).then(results => {
    // process results here
}).catch(err => {
    // handle error here
});

这样做的好处是,你可以&#34; promisify&#34;在项目中只有一次函数集的给定函数,然后只使用新的promisified版本。

假设您导入了一个包含大量这些类型接口的对象。然后,您可以自己创建一个promisifyObj()函数,为该对象上的所有函数创建一个promisified接口。

// a "Promise" version of every method on this object
function promisifyAll(obj) {
    let props = Object.keys(obj);
    props.forEach(propName => {
        // only do this for properties that are functions
        let fn = obj[propName];
        if (typeof fn === "function") {
            obj[propName + "Promise"] = promisify1(fn);
        }
    });
}

所以,如果你有一个名为myModule的对象,其中所有这些方法都带有这个非承诺接口,你就可以一步宣传该模块:

promisifyAll(myModule);

然后,您可以通过添加&#34; Promise&#34;来使用该对象中的任何方法。方法名称的后缀:

myModule.someMethodPromise(options).then(results => {
    // process results here
}).catch(err => {
    // handle error here
});